Results 1 to 3 of 3

Thread: store editing with grid selection model cannot be edited multiple times

    Looks like we can't reproduce the issue or there's a problem in the test case provided.
  1. #1
    Sencha Premium Member
    Join Date
    May 2009
    Posts
    3
    Vote Rating
    2
      0  

    Default store editing with grid selection model cannot be edited multiple times

    REQUIRED INFORMATION


    Ext version tested:
    • Ext 4.2.1
    Browser versions tested against:
    • IE9
    • Firefox 17
    • Chrome
    • phantomjs
    Description:
    • I'm trying to edit a store record by using the selection model. The second time I try to edit the record from the selectionmodel it does not update the store.
    Steps to reproduce the problem:
    1. load a store attached to a grid
    2. grab record using grid.getSelectionModel().getSelection()
    3. edit and save the record to a server
    4. on write event of the store, reload store
    5. try #2-3 again. store will not save to the server
    The result that was expected:
    • I should be able to keep editing a record, reload store, and edit that row again without having to select a different row and reselect the row I want to edit.
    Test Case:

    Code:
    var server = new MockHttpServer();
    server.start();
    
    
    server.handle = function (request) {
        request.setResponseHeader("Content-Type", "application/json");
        
        if(request.urlParts.path==='/dris/data/test.json'){
            json = {
                    rows :  [{
                        id : 3,
                        field1: 10,
                        field2: 'testdata'
                    }],
                    success: true,
                    total : 1
            };
            request.receive(200, Ext.encode(json) );
        }
        else if(request.urlParts.path=== '/dris/data/update.json'){
            json = {
                    rows :  [{
                        id : 3,
                        field1: 14,
                        field2: 'testdata2'
                    }],
                    success: true,
                    total : 1
            };
            request.receive(200, Ext.encode(json) );
        }
    };
    
    
    Ext.onReady(function(){
        Ext.create('Ext.data.Store',{
            autoLoad: true,
            autoSync: true,
            storeId: 'teststore',
            model: Ext.define('testmodel',{
                extend: 'Ext.data.Model',
                fields: [{
                    name:"id",
                    type:"int"
                },{
                    name:"field1",
                    type:"int"
                },{
                    name:"field2",
                    type:"string"
                }],
                proxy : {
                    type : 'ajax',
                    api: {
                        read: '/dris/data/test.json',
                        update: '/dris/data/update.json'
                    },
                    reader : {
                        type : 'json',
                        root: 'rows'
                    },
                    writer: {
                        type: 'json'
                    }
                }
            })
        });
        
        Ext.create('Ext.panel.Panel',{
            renderTo: Ext.get('center'),
            items: [{
                xtype: 'grid',
                id : 'testgrid',
                title : 'Data',
                region: 'center',
                enableColumnMove: false,
                columns : [{
                    header : 'ID',
                    dataIndex: 'id',
                    width: 100
                },{
                    header : 'Number',
                    dataIndex: 'field1',
                    width: 100
                },{
                    header : 'String',
                    dataIndex: 'field2',
                    width: 100
                }],
                store : 'teststore'
            }]
        });
    });
    
    
    
    
    describe("defect with saving a store and selecting the same row again", function() {        
        it("test", function() {
               var store = Ext.StoreMgr.get('teststore');        var grid = Ext.getCmp('testgrid');
            
            grid.getSelectionModel().select(0);
            
            var record = grid.getSelectionModel().getSelection()[0];
            record.set('field1',14);
            record.set('field2','testdata2');
            store.reload();
            var record = grid.getSelectionModel().getSelection()[0];
            expect(record.store).toBeNull();//the store is now missing from the record
            record.set('field1',15);
            record.set('field2','testdata3');
            expect(record.modified.field1).not.toBeNull();
            expect(record.modified.field2).not.toBeNull();
            
    //at this point the store record is not modifed even though I set two different fields on it.
            expect(store.getAt(0).modified.field1).toBeUndefined();
            expect(store.getAt(0).modified.field2).toBeUndefined();
        });
    });


    HELPFUL INFORMATION


    Debugging already done:
    • none
    Possible fix:
    • not provided
    Additional JS used:
    • using mock.js to mock xhr requests.
    • using jasmine.js to run unit tests
    Operating System:
    • Windows 7
    *EDIT BY SLEMMON
    Issue observed in 4.2.1, 4.2, 4.1.3, 4.1.1.
    Inline test case (modified the Writer example) with test sequence highlighted and bolded
    Code:
    Ext.define('Writer.Form', {
        extend: 'Ext.form.Panel',
        alias: 'widget.writerform',
    
    
        requires: ['Ext.form.field.Text'],
    
    
        initComponent: function(){
            this.addEvents('create');
            Ext.apply(this, {
                activeRecord: null,
                iconCls: 'icon-user',
                frame: true,
                title: 'User -- All fields are required',
                defaultType: 'textfield',
                bodyPadding: 5,
                fieldDefaults: {
                    anchor: '100%',
                    labelAlign: 'right'
                },
                items: [{
                    fieldLabel: 'Email',
                    name: 'email',
                    allowBlank: false,
                    vtype: 'email'
                }, {
                    fieldLabel: 'First',
                    name: 'first',
                    allowBlank: false
                }, {
                    fieldLabel: 'Last',
                    name: 'last',
                    allowBlank: false
                }],
                dockedItems: [{
                    xtype: 'toolbar',
                    dock: 'bottom',
                    ui: 'footer',
                    items: ['->', {
                        iconCls: 'icon-save',
                        itemId: 'save',
                        text: 'Save',
                        disabled: true,
                        scope: this,
                        handler: this.onSave
                    }, {
                        iconCls: 'icon-user-add',
                        text: 'Create',
                        scope: this,
                        handler: this.onCreate
                    }, {
                        iconCls: 'icon-reset',
                        text: 'Reset',
                        scope: this,
                        handler: this.onReset
                    }]
                }]
            });
            this.callParent();
        },
    
    
        setActiveRecord: function(record){
            this.activeRecord = record;
            if (record) {
                this.down('#save').enable();
                this.getForm().loadRecord(record);
            } else {
                this.down('#save').disable();
                this.getForm().reset();
            }
        },
    
    
        onSave: function(){
            var active = this.activeRecord,
                form = this.getForm();
    
    
            if (!active) {
                return;
            }
            if (form.isValid()) {
                form.updateRecord(active);
                this.onReset();
            }
        },
    
    
        onCreate: function(){
            var form = this.getForm();
    
    
            if (form.isValid()) {
                this.fireEvent('create', this, form.getValues());
                form.reset();
            }
    
    
        },
    
    
        onReset: function(){
            this.setActiveRecord(null);
            this.getForm().reset();
        }
    });
    
    
    Ext.define('Writer.Grid', {
        extend: 'Ext.grid.Panel',
        alias: 'widget.writergrid',
    
    
        requires: [
            'Ext.grid.plugin.CellEditing',
            'Ext.form.field.Text',
            'Ext.toolbar.TextItem'
        ],
    
    
        initComponent: function(){
    
    
            this.editing = Ext.create('Ext.grid.plugin.CellEditing');
    
    
            Ext.apply(this, {
                iconCls: 'icon-grid',
                frame: true,
                plugins: [this.editing],
                dockedItems: [{
                    xtype: 'toolbar',
                    items: [{
                        iconCls: 'icon-add',
                        text: 'Add',
                        scope: this,
                        handler: this.onAddClick
                    }, {
                        iconCls: 'icon-delete',
                        text: 'Delete',
                        disabled: true,
                        itemId: 'delete',
                        scope: this,
                        handler: this.onDeleteClick
                    }]
                }, {
                    weight: 2,
                    xtype: 'toolbar',
                    dock: 'bottom',
                    items: [{
                        xtype: 'tbtext',
                        text: '<b>@cfg</b>'
                    }, '|', {
                        text: 'autoSync',
                        enableToggle: true,
                        pressed: true,
                        tooltip: 'When enabled, Store will execute Ajax requests as soon as a Record becomes dirty.',
                        scope: this,
                        toggleHandler: function(btn, pressed){
                            this.store.autoSync = pressed;
                        }
                    }, {
                        text: 'batch',
                        enableToggle: true,
                        pressed: true,
                        tooltip: 'When enabled, Store will batch all records for each type of CRUD verb into a single Ajax request.',
                        scope: this,
                        toggleHandler: function(btn, pressed){
                            this.store.getProxy().batchActions = pressed;
                        }
                    }, {
                        text: 'writeAllFields',
                        enableToggle: true,
                        pressed: false,
                        tooltip: 'When enabled, Writer will write *all* fields to the server -- not just those that changed.',
                        scope: this,
                        toggleHandler: function(btn, pressed){
                            this.store.getProxy().getWriter().writeAllFields = pressed;
                        }
                    }]
                }, {
                    weight: 1,
                    xtype: 'toolbar',
                    dock: 'bottom',
                    ui: 'footer',
                    items: ['->', {
                        iconCls: 'icon-save',
                        text: 'Sync',
                        scope: this,
                        handler: this.onSync
                    }]
                }],
                columns: [{
                    text: 'ID',
                    width: 40,
                    sortable: true,
                    resizable: false,
                    draggable: false,
                    hideable: false,
                    menuDisabled: true,
                    dataIndex: 'id'
                }, {
                    header: 'Email',
                    flex: 1,
                    sortable: true,
                    dataIndex: 'email',
                    field: {
                        type: 'textfield'
                    }
                }, {
                    header: 'First',
                    width: 100,
                    sortable: true,
                    dataIndex: 'first',
                    field: {
                        type: 'textfield'
                    }
                }, {
                    header: 'Last',
                    width: 100,
                    sortable: true,
                    dataIndex: 'last',
                    field: {
                        type: 'textfield'
                    }
                }]
            });
            this.callParent();
            this.getSelectionModel().on('selectionchange', this.onSelectChange, this);
        },
        
        onSelectChange: function(selModel, selections){
            this.down('#delete').setDisabled(selections.length === 0);
        },
    
    
        onSync: function(){
            this.store.sync();
        },
    
    
        onDeleteClick: function(){
            var selection = this.getView().getSelectionModel().getSelection()[0];
            if (selection) {
                this.store.remove(selection);
            }
        },
    
    
        onAddClick: function(){
            var rec = new Writer.Person({
                first: '',
                last: '',
                email: ''
            }), edit = this.editing;
    
    
            edit.cancelEdit();
            this.store.insert(0, rec);
            edit.startEditByPosition({
                row: 0,
                column: 1
            });
        }
    });
    
    
    Ext.define('Writer.Person', {
        extend: 'Ext.data.Model',
        fields: [{
            name: 'id',
            type: 'int',
            useNull: true
        }, 'email', 'first', 'last'],
        validations: [{
            type: 'length',
            field: 'email',
            min: 1
        }, {
            type: 'length',
            field: 'first',
            min: 1
        }, {
            type: 'length',
            field: 'last',
            min: 1
        }]
    });
    
    
    Ext.require([
        'Ext.data.*',
        'Ext.tip.QuickTipManager',
        'Ext.window.MessageBox'
    ]);
    
    
    Ext.onReady(function(){
        Ext.tip.QuickTipManager.init();
        
        Ext.create('Ext.button.Button', {
            margin: '0 0 20 20',
            text: 'Reset sample database back to initial state',
            renderTo: document.body,
            tooltip: 'The sample database is stored in the session, including any changes you make. Click this button to reset the sample database to the initial state',
            handler: function(){
                Ext.getBody().mask('Resetting...');
                Ext.Ajax.request({
                    url: 'app.php/example/reset',
                    callback: function(options, success, response) {
                        Ext.getBody().unmask();
                        
                        var didReset = true,
                            o;
                        
                        if (success) {
                            try {
                                o = Ext.decode(response.responseText);
                                didReset = o.success === true;
                            } catch (e) {
                                didReset = false;
                            }
                        } else {
                            didReset = false;
                        }
                        
                        if (didReset) {
                            store.load();
                            main.down('#form').setActiveRecord(null);
                            Ext.example.msg('Reset', 'Reset successful');
                        } else {
                            Ext.MessageBox.alert('Error', 'Unable to reset example database');
                        }
                        
                    }
                });
            }
        })
        
        var store = Ext.create('Ext.data.Store', {
            model: 'Writer.Person',
            autoLoad: true,
            autoSync: true,
            proxy: {
                type: 'ajax',
                api: {
                    read: 'app.php/users/view',
                    create: 'app.php/users/create',
                    update: 'app.php/users/update',
                    destroy: 'app.php/users/destroy'
                },
                reader: {
                    type: 'json',
                    successProperty: 'success',
                    root: 'data',
                    messageProperty: 'message'
                },
                writer: {
                    type: 'json',
                    writeAllFields: false,
                    root: 'data'
                },
                listeners: {
                    exception: function(proxy, response, operation){
                        Ext.MessageBox.show({
                            title: 'REMOTE EXCEPTION',
                            msg: operation.getError(),
                            icon: Ext.MessageBox.ERROR,
                            buttons: Ext.Msg.OK
                        });
                    }
                }
            },
            listeners: {
                write: function(proxy, operation){
                    if (operation.action == 'destroy') {
                        main.child('#form').setActiveRecord(null);
                    }
                    Ext.example.msg(operation.action, operation.resultSet.message);
                }
            }
        });
    
    
        var main = Ext.create('Ext.container.Container', {
            padding: '0 0 0 20',
            width: 500,
            height: Ext.themeName === 'neptune' ? 500 : 450,
            renderTo: document.body,
            layout: {
                type: 'vbox',
                align: 'stretch'
            },
            items: [{
                itemId: 'form',
                xtype: 'writerform',
                manageHeight: false,
                margins: '0 0 10 0',
                listeners: {
                    create: function(form, data){
                        store.insert(0, data);
                    }
                }
            }, {
                itemId: 'grid',
                xtype: 'writergrid',
                title: 'User List',
                flex: 1,
                store: store,
                listeners: {
                    selectionchange: function(selModel, selected) {
                        main.child('#form').setActiveRecord(selected[0] || null);
                    },
                    viewready: {
                        fn: function (view) {
                            var grid = main.down('writergrid');
                            var selModel = grid.getSelectionModel();
    
    
                            selModel.select(1);
    
    
                            var record = selModel.getSelection()[0];
                            record.set('first',14);
                            record.set('last','testdata2');
                            grid.getStore().reload({
                                callback: function () {
                                    // deselect > select to remedy
                                    // selModel.deselectAll();
                                    // selModel.select(1);
                                    var record = grid.getSelectionModel().getSelection()[0];
                                    record.set('first',15);
                                    record.set('last','testdata3');
                                }
                            });
                        },
                        delay: 1000
                    }
                }
            }]
        });
    });
    Last edited by slemmon; 13 Jun 2013 at 12:16 PM. Reason: additional test notes

  2. #2
    Sencha - Support Team slemmon's Avatar
    Join Date
    Mar 2009
    Location
    Boise, ID
    Posts
    6,154
    Vote Rating
    247
      0  

    Default

    Thanks for the report! I have opened a bug in our bug tracker.

  3. #3
    Sencha User
    Join Date
    Jun 2014
    Location
    Sweden
    Posts
    12
    Vote Rating
    0
      0  

    Default

    What is the status of this? I'm having this problem also with Ext JS 5.1.

Tags for this Thread

Posting Permissions

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