Results 1 to 5 of 5

Thread: Grid/Code improvements wanted!

  1. #1
    Sencha User Gr3yh0und's Avatar
    Join Date
    Aug 2011
    Location
    Germany
    Posts
    10

    Exclamation Answered: Grid/Code improvements wanted!

    Hey guys,

    I'm relatively new to ExtJS and just working the last 4 weeks on a larger website with ExtJS embedded. I had some troubles with grids n stuff and have many things "borrowed" from other code.

    Maybe someone can have a short look at my grid example (most of them are very similiar) and maybe can give me some tips on how to tune/make it nicer or more secure for later updates? New features or ideas are also welcome!

    Thank you!

    It basically looks like:

    Code:
    // Enable config
        Ext.Loader.setConfig({
            enabled: true
        });
        
        // Set Path
        Ext.Loader.setPath('Ext.ux', 'extjs/examples/ux');
        
        // Include required libraries
        Ext.require([
            'Ext.grid.*',
            'Ext.data.*',
            'Ext.util.*',
            'Ext.state.*',
            'Ext.form.*',
            'Ext.tab.*',
            'Ext.ux.grid.FiltersFeature',
            'Ext.ux.CheckColumn',
            'Ext.ux.RowExpander',
            'Ext.toolbar.Paging',
            'Ext.tip.QuickTipManager'
        ]);
    Just prethings...

    Now the datamodel (MySQL and MSSQL Backend with php):
    Code:
    // Define our data models
        Ext.define('Location', {
            extend: 'Ext.data.Model',
            fields: ['id', 'idcity', 'short', 'ads',  'name', 'street', 'postal', 'city', 'comment', 'assetlink']
        });
    
    // Define Proxy for reading/writing Data to Store
    // Location
        var proxy_location = new Ext.data.proxy.Ajax({
            type: 'ajax',
            autoSave: true,
            url: 'config/api_mysql.php',
            extraParams: {
                select: 'id, idcity, short, ads, comment, name, street, postal, city, assetlink',
                table:    'location',
                order:    'short ASC'
            },
            actionMethods: {
                read:         'POST',
                update:     'POST',
                create:     'POST',
                destroy:     'POST'
            },
            reader: {
                type:             'json',
                model:             'Location',
                root:             'results',
                totalProperty:     'total',
                idProperty:     'id'
            },
            writer: {
                type:         'json',
                model:         'Location',
                root:         'results',
                encode:     'true'  
                
            },
            api: {
                read:        'config/api_mysql.php?do=read',
                update:     'config/api_mysql.php?do=update',
                create:     'config/api_mysql.php?do=create',
                destroy:     'config/api_mysql.php?do=destroy'
            }
        });
    
    // Define data Stores
        // Location
        var store_location = new Ext.data.Store({
            model: 'Location',
            pageSize: 21,
            proxy: proxy_location
        });
    Now the form to add a new entry:
    Code:
    // Location Add Form
        function locationAddForm() {
            Ext.create('widget.window', {
                title: 'Neue Lokation erstellen',
                closeAction: 'hide',
                renderTo: document.body,
                width: 300,
                height: 600,
                minHeight: 400,
                layout: 'fit',
                resizable: true,
                modal: true,
                defaults: {
                    anchor: '100%'
                },
                items: {
                    // Formpanel
                    xtype: 'form',
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    border: false,
                    bodyPadding: 10,
                    fieldDefaults: {
                        labelAlign: 'top',
                        labelWidth: 100,
                        labelStyle: 'font-weight:bold'
                    },
                    defaults: {
                        margins: '0 0 10 0'
                    },
                    items: [
                    // Formfields
                    {
                        xtype: 'textfield',
                        id: 'short',
                        fieldLabel: 'Lokationskuerzel im Format: AAA000-0',
                        allowBlank: false
                    }, {
                        xtype: 'textfield',
                        id: 'name',
                        fieldLabel: 'Bezeichnung',
                        allowBlank: false
                    }, {
                        xtype: 'combo',
                        id: 'idcity_add',
                        fieldLabel: 'Uebergeordneter Standort',
                        labelWidth: 125,
                        store: store_city,
                        queryMode: 'local',
                        displayField: 'title',
                        valueField: 'id'
                    }, {
                        xtype: 'textfield',
                        id: 'ads',
                        fieldLabel: 'AD-Pfad',
                        allowBlank: true
                    }, {
                        xtype: 'fieldcontainer',
                        fieldLabel: 'Adresse',
                        labelStyle: 'font-weight:bold;padding:0',
                        layout: 'hbox',
                        defaultType: 'textfield',
                        fieldDefaults: {
                            labelAlign: 'top'
                        },
                        items: [{
                            flex: 3,
                            id: 'street',
                            fieldLabel: 'Strasse',
                            allowBlank: true
                        }, {
                            flex: 1,
                            id: 'postal',
                            fieldLabel: 'PLZ',
                            margins: '0 0 0 5',
                            allowBlank: true
                        }, {
                            flex: 2,
                            id: 'city',
                            fieldLabel: 'Ort',
                            allowBlank: false,
                            margins: '0 0 0 5',
                            allowBlank: true
                        }]
                    }, {
                        xtype: 'textareafield',
                        id: 'comment',
                        fieldLabel: 'Kommentar',
                        labelAlign: 'top',
                        flex: 3,
                        margins: '0',
                        allowBlank: true
                    }, {
                        xtype: 'textfield',
                        id: 'assetlink',
                        fieldLabel: 'AssetDesk Link',
                        allowBlank: true
                    }],
                    buttons: [{
                        text: 'Abbrechen',
                        handler: function () {
                            this.up('form').getForm().reset();
                            this.up('window').destroy();
                        }
                    }, {
                        text: 'Erstellen',
                        handler: function () {
                            if (this.up('form').getForm().isValid()) {
                                var short = Ext.getCmp('short').getValue();
                                
                                // Create record and save
                                var r = Ext.ModelManager.create({
                                    id: '',
                                    idcity: Ext.getCmp('idcity_add').getValue(),
                                    short: Ext.getCmp('short').getValue(),
                                    ads: Ext.getCmp('ads').getValue(),
                                    name: Ext.getCmp('name').getValue(),
                                    street: Ext.getCmp('street').getValue(),
                                    postal: Ext.getCmp('postal').getValue(),
                                    city: Ext.getCmp('city').getValue(),
                                    comment: Ext.getCmp('comment').getValue(),
                                    assetlink: Ext.getCmp('assetlink').getValue()
                                }, 'Location');
                                store_location.insert(0, r);
                                store_location.save();
                                this.up('form').getForm().reset();
                                this.up('window').destroy();
                                Ext.MessageBox.alert('Success!', 'Die neue Lokation ' + short + ' wurde erfolgreich angelegt!');
                                store_location.load(); 
                            }
                        }
                    }],
                    listeners: {
                        'beforerender': function(){
                            store_city.load();
                        }
                    }
                }
            }).show();
        }
    And the second one to edit an entry:
    Code:
    // Location Edit Form
        function locationEditForm(editid) {
            Ext.widget('window', {
                title: 'Edit',
                closeAction: 'hide',
                width: 300,
                height: 600,
                minHeight: 400,
                layout: 'fit',
                resizable: true,
                modal: true,
                items: {
                    xtype: 'form',
                    layout: {
                        type: 'vbox',
                        align: 'stretch'
                    },
                    border: false,
                    bodyPadding: 10,
                    fieldDefaults: {
                        labelAlign: 'top',
                        labelWidth: 100,
                        labelStyle: 'font-weight:bold'
                    },
                    defaults: { margins: '0 0 10 0'    },
                    // Textfields
                    items: [ {
                        xtype: 'hiddenfield',
                        id: 'id'
                    },{
                        xtype: 'textfield',
                        id: 'short',
                        fieldLabel: 'Lokationskuerzel im Format: AAA000-0',
                        allowBlank: false
                    },{
                        xtype: 'textfield',
                        id: 'name',
                        fieldLabel: 'Bezeichnung',
                        allowBlank: false
                    },{
                        xtype: 'combo',
                        id: 'idcity',
                        fieldLabel: 'Uebergeordneter Standort',
                        labelWidth: 125,
                        store: store_city,
                        queryMode: 'local',
                        displayField: 'title',
                        valueField: 'id'
                    },{
                        xtype: 'textfield',
                        id: 'ads',
                        fieldLabel: 'AD-Pfad',
                        allowBlank: true
                    },{
                        xtype: 'fieldcontainer',
                        fieldLabel: 'Adresse',
                        labelStyle: 'font-weight:bold;padding:0',
                        layout: 'hbox',
                        defaultType: 'textfield',
                        fieldDefaults: { labelAlign: 'top' },
                        items: [{
                            flex: 3,
                            id: 'street',
                            fieldLabel: 'Strasse',
                            allowBlank: true
                        }, {
                            flex: 1,
                            id: 'postal',
                            fieldLabel: 'PLZ',
                            margins: '0 0 0 5',
                            allowBlank: true
                        }, {
                            flex: 2,
                            id: 'city',
                            fieldLabel: 'Ort',
                            allowBlank: false,
                            margins: '0 0 0 5',
                            allowBlank: true
                        }]
                    },{
                        xtype: 'textareafield',
                        id: 'comment',
                        fieldLabel: 'Kommentar',
                        labelAlign: 'top',
                        flex: 3,
                        margins: '0',
                        allowBlank: true
                    },{
                        xtype: 'textfield',
                        id: 'assetlink',
                        fieldLabel: 'AssetDesk Link',
                        allowBlank: true
                    }
                    ],
                    buttons: [{
                        text: 'Schliessen',
                        handler: function() {
                            this.up('form').getForm().reset();
                            this.up('window').destroy();
                        }
                    },{
                        text: 'Speichern',
                        handler: function() {
                            if (this.up('form').getForm().isValid()) {
                                var record = store_location.getById(editid); // get record
                                // Edit record
                                record.set('short', Ext.getCmp('short').getValue());
                                record.set('idcity', Ext.getCmp('idcity').getValue());
                                record.set('ads', Ext.getCmp('ads').getValue());
                                record.set('name', Ext.getCmp('name').getValue());
                                record.set('street', Ext.getCmp('street').getValue());
                                record.set('postal', Ext.getCmp('postal').getValue());
                                record.set('city', Ext.getCmp('city').getValue());
                                record.set('comment', Ext.getCmp('comment').getValue());
                                record.set('assetlink', Ext.getCmp('assetlink').getValue());
                                
                                // Update store and reset form
                                store_location.sync();
                                Ext.MessageBox.alert('Success!', Ext.getCmp('short').getValue() + ' wurde erfolgreich geaendert!');
                                this.up('form').getForm().reset();
                                this.up('window').destroy();
                            }
                        }
                    }],
                    listeners: {
                        // Load Data from Entry
                        beforerender: {
                            fn: function() { 
                                store_city.load();
                                this.getForm().loadRecord(store_location.getById(editid)); 
                            }
                        }
                    }
                }
            }).show();
        }
    Now some function to add image to a row:
    Code:
        // Render icon for grid YES/NO
        function rendericon(value) {
            if(value == null){
                return '<img src="extjs/resources/themes/images/default/dd/drop-no.gif">';
            }else{
                return '<img src="extjs/resources/themes/images/default/dd/drop-yes.gif">';
            }
        }
    And the coloumns with my action images:
    Code:
    // Define Grid coloumns
    // Location
        var columns_location = [
        { id: 'location_short', header: 'Index', dataIndex: 'short', flex: 1, sortable: true, editor: {allowBlank: false} },
        { id: 'location_name', header: 'Bezeichnung', dataIndex: 'name', flex: 1, sortable: true, editor: {allowBlank: false} },
        { id: 'location_street', header: 'Strasse', dataIndex: 'street', flex: 2, sortable: true, editor: {allowBlank: false} },
        { id: 'location_postal', header: 'PLZ', dataIndex: 'postal', flex: 1, sortable: true, editor: {allowBlank: false} },
        { id: 'location_city', header: 'Ort', dataIndex: 'city', flex: 1, sortable: true, editor: {allowBlank: false} },
        { id: 'location_ads', header: 'AD', renderer:rendericon, dataIndex: 'ads',  textAlign: 'center', sortable: true, width: 30 },
        { 
            xtype: 'actioncolumn',
            header: 'Aktion',
            width:40,
            items: [{
                // Edit row
                icon: 'extjs/examples/shared/icons/fam/cog_edit.png',  
                tooltip: 'Editieren',
                handler: function(grid, rowIndex, colIndex) {
                    locationEditForm(grid.getStore().getAt(rowIndex).get('id'));
                }
            },{
                // Delete row
                icon: 'extjs/examples/restful/images/delete.png',
                tooltip: 'Loeschen',
                handler: function(grid, rowIndex, colIndex) {
                    var sm = grid.getSelectionModel();
                    store_location.remove(sm.getSelection());
                    sm.select(0);
                    store_location.save();
                }
            }]
        },{ 
            xtype: 'actioncolumn',
            header: 'Link',
            width:40,
            items: [{
                // Link to AssetDesk
                icon: 'resources/images/asset.png',
                tooltip: 'AssetDesk',
                handler: function(grid, rowIndex, colIndex) {
                    if(grid.getStore().getAt(rowIndex).get('assetlink')){
                        window.location = grid.getStore().getAt(rowIndex).get('assetlink')
                    }else{
                        Ext.MessageBox.alert('Error!', grid.getStore().getAt(rowIndex).get('short') + ': Kein Link zu AssetDesk hinterlegt!');
                    }
                }
            },{
                // Link to details page
                icon: 'extjs/examples/shared/icons/fam/application_go.png',
                tooltip: 'Details',
                handler: function(grid, rowIndex, colIndex) {
                    window.location = "index.php?section=single&id=" + grid.getStore().getAt(rowIndex).get('id') + "&short=" + grid.getStore().getAt(rowIndex).get('short')
                }
            }]
        }
        ];
    Now the main grid in a tab:
    Code:
    // Main function
        Ext.onReady(function() {
        
            // Enable tooltips
            Ext.tip.QuickTipManager.init();
    
    // Create Tabs with everything
            var tabpanel = Ext.create('Ext.tab.Panel', {
                renderTo: 'editor-grid',
                activeTab: 0,
                width: 800,
                height: 600,
                plain: true,
                layout: 'fit',
                border: true,
                closable: false,
                defaults :{
                    autoScroll: true,
                    layout:'fit'
                },
            });
    
    // Create Location Grid panel
            tabpanel.add({
                xtype: 'grid',
                itemID: 'location',
                title: 'Lokationen',
                store: store_location,
                columns: columns_location,
                frame: false,
                width: 800,
                height: 587,
                loadMask: true,
                dockedItems: [{
                    // Paging
                    xtype: 'pagingtoolbar',
                    store: store_location,
                    dock: 'bottom',
                    displayInfo: true,
                    pageSize: 21
                },{ 
                    xtype: 'toolbar',
                    dock: 'top', 
                    items: [{ 
                        // Create Button
                        xtype: 'button', 
                        text: 'Erstellen', 
                        icon: 'extjs/resources/themes/images/default/dd/drop-add.gif', 
                        handler: locationAddForm
                    }] 
                }],
                listeners: {
                    'activate': function(){
                        store_location.load();
                    },
                    'edit': function(data){
                        store_location.save();
                    }
                }
            });
    Sorry for the german headings

  2. A few thoughts...

    Avoid using component ids. Give fields a name instead.

    You may be able to simplify things using getFieldValues:

    http://docs.sencha.com/ext-js/4-0/#!...getFieldValues

    e.g.:

    Code:
    record.set(form.getForm().getFieldValues());
    You may also find updateRecord to be of interest as you're using loadRecord:

    http://docs.sencha.com/ext-js/4-0/#!...d-updateRecord

    Even if you choose not to use updateRecord you may find it interesting to read the source code for it.

    There's an unnecessary type option here:

    Code:
    var proxy_location = new Ext.data.proxy.Ajax({
        type: 'ajax',
    This seems a little strange too, why set an anchor when you're using fit layout?

    Code:
    layout: 'fit',
    ...
    defaults: {
        anchor: '100%'
    },
    I'm a bit dubious about the existence of the function locationEditForm. Looks a bit global to me. Can't you just move all the window config options into a subclass then get rid of that function (your handler would just be a one-liner to instantiate the class instead)? I think overall a lot of your code would be benefit from being moved into classes rather than using large configs.

  3. #2
    Touch Premium Member
    Join Date
    Jun 2011
    Posts
    1,102
    Answers
    113

    Default

    You can probably use the same form for add and edit and just make some changes depending on whether it was called for add or edit. You don't need to create a new record. You can directly insert a new record in a store like this:

    Code:
    store.insert(0, {id: value1, name: value2, address: value3});
    where id, name, address etc. would be the fields in your model and value1, value2, etc. would be the values you get from your form fields. Similarly, you can just call record.set only once and set all the values at one time.

    Code:
    record.set({id: value1, name: value2, address: value3});
    what would be better is that you could use the rowediting plugin in the grid. this would allow you to edit and add entries directly in the grid without using a form!

    If you have some specific questions, you may ask. Most people won't read your whole code...

    Regards,
    Farish

  4. #3
    Sencha User Gr3yh0und's Avatar
    Join Date
    Aug 2011
    Location
    Germany
    Posts
    10

    Default

    Thanks for your fast answer Farish!

    I will try to tune to just use one form. The background is, that I actually don't want to display all data in the grid, so often a formular is necessary...

    I just struggled during my programming stuff with some implementations for ExtJS 2.x and 3.x... There are a lot of variations out the (i.e. the grid selection which is now "selection" and was "selections" before... Took me one day to figure that out). My idea was just to make it more "compliant" for further operations

  5. #4
    Touch Premium Member
    Join Date
    Jun 2011
    Posts
    1,102
    Answers
    113

    Default

    Ich habe auch vor ca. 6 Monaten mit ExtJS angefangen and es war wirklich schwer!

    Gru,
    Farish

  6. #5
    Sencha Premium Member skirtle's Avatar
    Join Date
    Oct 2010
    Location
    UK
    Posts
    3,791
    Answers
    585

    Default

    A few thoughts...

    Avoid using component ids. Give fields a name instead.

    You may be able to simplify things using getFieldValues:

    http://docs.sencha.com/ext-js/4-0/#!...getFieldValues

    e.g.:

    Code:
    record.set(form.getForm().getFieldValues());
    You may also find updateRecord to be of interest as you're using loadRecord:

    http://docs.sencha.com/ext-js/4-0/#!...d-updateRecord

    Even if you choose not to use updateRecord you may find it interesting to read the source code for it.

    There's an unnecessary type option here:

    Code:
    var proxy_location = new Ext.data.proxy.Ajax({
        type: 'ajax',
    This seems a little strange too, why set an anchor when you're using fit layout?

    Code:
    layout: 'fit',
    ...
    defaults: {
        anchor: '100%'
    },
    I'm a bit dubious about the existence of the function locationEditForm. Looks a bit global to me. Can't you just move all the window config options into a subclass then get rid of that function (your handler would just be a one-liner to instantiate the class instead)? I think overall a lot of your code would be benefit from being moved into classes rather than using large configs.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •