1. #1
    Ext JS Premium Member
    Join Date
    Mar 2010
    Posts
    227
    Vote Rating
    2
    alphadogg is on a distinguished road

      0  

    Default Managing Grid CRUD In ExtJS4

    Managing Grid CRUD In ExtJS4


    I've setup a nice autosynching grid that allows cell-level editing. I have the "preferred way" of having a grid, a store, a model w/embedded proxy, JSON readers and writers. It reads data from the remote server via the AJAX proxy beautifully. It sends out CRUD messages as expected.

    But, what then? There seems to be no example, tutorials or API documentation that addresses responding to the server's feedback on the CRUD actions. The demos seem to be read-only. I see one demo with an exception listener on the store, another demo has a write listener on the store for a specific. The API has no explanation of this aspect of grid usage. The community manual is outdated.

    This isn't an esoteric, edge case, is it? Shouldn't there be something somewhere on what 2/3 of grid users are probably doing right now?

  2. #2
    Sencha User
    Join Date
    Oct 2010
    Posts
    159
    Vote Rating
    0
    mdavis6890 is on a distinguished road

      0  

    Default


    First, make sure that you have autoSync set on your store. Every edit to the grid get's synced back to the store, and then the store automatically sends a CRUD back to the server via the writer.

    You might later decide not to use the autoSync feature and replace it with a button that does grid.store.save(), but it's a start.

    In your server code, I suggest that you return the modified or inserted records whenever you perform those actions. and don't forget {success : true (or false) } as well.

  3. #3
    Sencha User
    Join Date
    Nov 2010
    Location
    Canton, GA, USA
    Posts
    20
    Vote Rating
    1
    pauldugas is on a distinguished road

      0  

    Default


    That last bit, returning the modified records. Is there a specific format that they should be returned in? What does this accomplish?

  4. #4
    Sencha User
    Join Date
    Oct 2010
    Posts
    159
    Vote Rating
    0
    mdavis6890 is on a distinguished road

      0  

    Default


    Return the records in the same way that you do to build the grid store. Doing this will allow the store to update it's own record accordingly. It's sort of a re-check of that record, just to make sure that what's in the store is truly reflecting what's in the database.

    For example, suppose that you create a new record in the store, but that your database also has an auto-generated id field. Or maybe a you have a last-updated-time field that the database auto-updates for you. You want to read that back into the store so that everything matches up.

  5. #5
    Ext JS Premium Member
    Join Date
    Mar 2010
    Posts
    227
    Vote Rating
    2
    alphadogg is on a distinguished road

      0  

    Default


    So, I do have autoSync on, and I do end up sending CRUD to the server. But, when I edit a cell, I get the "red triangle" which doesn't go away nor is the store reset, such that if I edit another cell, I will issue two updates.

    Here's the code I have so far.

    Code:
        Ext.onReady(function() {
        
            Ext.BLANK_IMAGE_URL = '/images/extjs4/s.gif';
            Ext.tip.QuickTipManager.init();
    
            Ext.define('VendorError', {
                extend: 'Ext.data.Model',
                fields: [
                    {name: 'id', type: 'int'},
                    {name: 'VendorID', type: 'int'},
                    {name: 'VendorName', type: 'string'},
                    {name: 'VndActID', type: 'int'},
                    {name: 'VndActNb', type: 'string'},
                    {name: 'InvoiceID', type: 'int'},
                    {name: 'VInvNb', type: 'string'},
                    {name: 'VInvRcptDt', type: 'date', dateFormat: 'Y-m-d' },
                    {name: 'InvDate', type: 'date', dateFormat: 'Y-m-d' },
                    {name: 'CodeSpecifier', type: 'string'},
                    {name: 'Recurrence', type: 'string'},
                    {name: 'ClientID', type: 'int'},
                    {name: 'ClientName', type: 'string'},
                    {name: 'LocID', type: 'int'},
                    {name: 'LocName', type: 'string'},
                    {name: 'RecentLocStatus', type: 'string'},
                    {name: 'RecentLocStatusDate', type: 'date', dateFormat: 'Y-m-d' },
                    {name: 'UnexpCost', type: 'float'},
                    {name: 'ConfirmedAmt', type: 'float'},
                    {name: 'StaffID', type: 'int'},
                    {name: 'NetworkID', type: 'string'},
                    {name: 'UnexpStatCode', type: 'string'}
                ],
                proxy: {
                    type: 'ajax',
                    simpleSortMode: true,
                    api: {
                        read:    '/internal/viewVERext_json.asp',
                        create:  '/internal/viewVERext_create.asp',
                        update:  '/internal/viewVERext_update.asp',
                        destroy: '/internal/viewVERext_destroy.asp'
                    },
                    reader: {
                        type: 'json',
                        messageProperty: 'message',
                        root: 'data'
                    },
                    writer: {
                        type: 'json',
                        writeAllFields: true,
                        allowSingle: false,
                        root: 'data'
                    },
                    listeners: {
                        exception: function(proxy, response, operation){
                            Ext.MessageBox.show({
                                title: 'ERROR',
                                msg: operation.getError(),
                                icon: Ext.MessageBox.ERROR,
                                buttons: Ext.Msg.OK
                            });
                        }
                    }
                }
            });
            
            var store = Ext.create('Ext.data.Store', {
                model: 'VendorError',
                autoLoad: true,
                autoSync: true,
                pageSize: 20,
                remoteSort: true
            });
    
            // create the Grid
            var grid = Ext.create('Ext.grid.Panel', {
                store: store,
                columns: [
                    {    text     : 'Vendor',
                        dataIndex: 'VendorName',
                        flex     : 1
                    },
                    {    text     : 'Account',
                        dataIndex: 'VndActNb'
                    },
                    {    text     : 'Invoice',
                        dataIndex: 'VInvNb'
                    },
                    {    text     : 'Invoiced',
                        dataIndex: 'InvDate', 
                        xtype    : 'datecolumn',
                        align    : 'center'
                    },
                    {    text     : 'Receipted',
                        dataIndex: 'VInvRcptDt', 
                        xtype    : 'datecolumn',
                        align    : 'center'
                    },
                    {    text     : 'Description',
                        dataIndex: 'CodeSpecifier'
                    },
                    {    text     : 'Client',
                        dataIndex: 'ClientName'
                    },
                    {    text     : 'Location',
                        dataIndex: 'LocName'
                    },
                    {    text     : 'LStatus',
                        dataIndex: 'RecentLocStatus',
                        align    : 'center'
                    },
                    {    text     : 'Credit',
                        dataIndex: 'UnexpCost',
                        tdCls    : 'colyellow',
                        renderer : Ext.util.Format.usMoney,
                        align    : 'right',
                        field    : { xtype:'textfield', allowBlank:false }
                    },
                    {    text     : 'Confirmed',
                        dataIndex: 'ConfirmedAmt',
                        tdCls    : 'colyellow',
                        renderer : Ext.util.Format.usMoney,
                        align    : 'right',
                        field    : { xtype:'textfield', allowBlank:false }
                    },
                    {    text     : 'Recurrence',
                        dataIndex: 'Recurrence',
                        tdCls    : 'colyellow',
                        align    : 'center',
                        field    : {
                            xtype    : 'combobox',
                            typeAhead: true,
                            triggerAction: 'all',
                            selectOnTab: true,
                            store: [
                                ['once','once'],['1st','1st'],['2nd+','2nd+']
                            ],
                            lazyRender: true
                        }
                    },
                    {    text     : 'CStatus',
                        dataIndex: 'UnexpStatCode',
                        tdCls    : 'colyellow',
                        align    : 'center',
                        field    : {
                            xtype    : 'combobox',
                            typeAhead: true,
                            triggerAction: 'all',
                            selectOnTab: true,
                            store: [
                                <%=cstat_grid%>
                            ],
                            lazyRender: true
                        }
                    },
                    {    text     : 'Owner',
                        dataIndex: 'NetworkID',
                        tdCls    : 'colyellow',
                        field    : {
                            xtype    : 'combobox',
                            typeAhead: true,
                            triggerAction: 'all',
                            selectOnTab: true,
                            store: [
                                <%=staff_grid%>
                            ],
                            lazyRender: true
                        }
                    }
                ],
                layout: 'fit',
                height: 500,
                renderTo: 'theGrid',
                selType: 'cellmodel',
                plugins: [
                    Ext.create('Ext.grid.plugin.CellEditing', {
                        clicksToEdit: 1
                    })
                ],
                dockedItems: [
                    { xtype: 'pagingtoolbar',
                        store: store,
                        dock: 'bottom',
                        displayInfo: true
                    },
                    { xtype: 'toolbar',
                        dock: 'top',
                        items: [
                            { xtype:'button', 
                              text: 'IsDirty()', 
                              handler: function() { 
                      var report = "";
                      store.each( function(rec) { report = report + rec.dirty + '/'; } );
                      alert(report);
                                }
                            }
                        ]
                    }
                ],
                viewConfig: {
                    stripeRows: true
                }
            });
            
            Ext.EventManager.onWindowResize(grid.doLayout, grid);
        });

  6. #6
    Sencha User
    Join Date
    Oct 2010
    Posts
    159
    Vote Rating
    0
    mdavis6890 is on a distinguished road

      0  

    Default


    By the way, this is easy with PostgreSQL, where you can use "INSERT/UPDATE ..... RETURNING *"

  7. #7
    Ext JS Premium Member
    Join Date
    Mar 2010
    Posts
    227
    Vote Rating
    2
    alphadogg is on a distinguished road

      0  

    Default


    Here's the POSTed data from the grid/store/model (as seen in Firebug). What I did was went into ConfirmedAmt cell for this record in the grid, and changed 21.11 to 0.

    Code:
    {
        "data": [
            {
                "id": 17545,
                "VendorID": 387069,
                "VendorName": "xxxxxx",
                "VndActID": 5971516,
                "VndActNb": "xxxxx",
                "InvoiceID": 9704415,
                "VInvNb": "3317755-1376-4",
                "VInvRcptDt": "2011-04-18T00:00:00",
                "InvDate": "2011-04-01T00:00:00",
                "CodeSpecifier": "Invalid rate increase on Infrastructure Maintenance Fee.",
                "Recurrence": "1st",
                "ClientID": 7066314,
                "ClientName": "xxxxx",
                "LocID": 0,
                "LocName": "xxxxx",
                "RecentLocStatus": "ACT",
                "RecentLocStatusDate": "2010-09-09T00:00:00",
                "UnexpCost": 21,
                "ConfirmedAmt": 0,
                "StaffID": 0,
                "NetworkID": "",
                "UnexpStatCode": "RUS"
            }
        ]
    }

  8. #8
    Ext JS Premium Member
    Join Date
    Mar 2010
    Posts
    227
    Vote Rating
    2
    alphadogg is on a distinguished road

      0  

    Default


    Here's the response I send back (as seen in Firebug):
    Code:
    {
        "success": true,
        "message": "Awesomesauce.",
        "data": [
            {
                "id": 17545,
                "VendorID": 387069,
                "VendorName": "xxxxxx",
                "VndActID": 5971516,
                "VndActNb": "xxxxxx",
                "InvoiceID": 9704415,
                "VInvNb": "3317755-1376-4",
                "VInvRcptDt": "2011-04-18T00:00:00",
                "InvDate": "2011-04-01T00:00:00",
                "CodeSpecifier": "Invalid rate increase on Infrastructure Maintenance Fee. ",
                "Recurrence": "1st",
                "ClientID": 7066314,
                "ClientName": "xxxxxxx",
                "LocID": 0,
                "LocName": "xxxxxx",
                "RecentLocStatus": "ACT",
                "RecentLocStatusDate": "2010-09-09T00:00:00",
                "UnexpCost": 21,
                "ConfirmedAmt": 0,
                "StaffID": 0,
                "NetworkID": "",
                "UnexpStatCode": "RUS"
            }
        ]
    }

  9. #9
    Sencha User
    Join Date
    Oct 2010
    Posts
    159
    Vote Rating
    0
    mdavis6890 is on a distinguished road

      0  

    Default


    Well, that looks like it ought to work, but now that you mention it, my grid is having this particular problem as well. I don't get multiple CRUD requests as I go along though, I only have extraneous red triangles. Are you really getting multiple requests as you edit additional data?

  10. #10
    Sencha User
    Join Date
    Mar 2011
    Location
    Germany
    Posts
    198
    Vote Rating
    1
    Nickname is on a distinguished road

      0  

    Default


    Quote Originally Posted by alphadogg View Post
    So, I do have autoSync on, and I do end up sending CRUD to the server. But, when I edit a cell, I get the "red triangle" which doesn't go away nor is the store reset, such that if I edit another cell, I will issue two updates.
    Could be related to this bug: http://www.sencha.com/forum/showthre...ate-dirty-flag