Ext.require(['Ext.data.*', 'Ext.grid.*']); Ext.define('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.onReady(function(){ var store = Ext.create('Ext.data.Store', { autoLoad: true, autoSync: true, model: 'Person', proxy: { type: 'rest', url: 'app.php/users', reader: { type: 'json', root: 'data' }, writer: { type: 'json' } }, listeners: { write: function(store, operation){ var record = operation.getRecords()[0], name = Ext.String.capitalize(operation.action), verb; if (name == 'Destroy') { record = operation.records[0]; verb = 'Destroyed'; } else { verb = name + 'd'; } Ext.example.msg(name, Ext.String.format("{0} user: {1}", verb, record.getId())); } } }); var rowEditing = Ext.create('Ext.grid.plugin.RowEditing'); var grid = Ext.create('Ext.grid.Panel', { renderTo: document.body, plugins: [rowEditing], width: 400, height: 300, frame: true, title: 'Users', store: store, iconCls: 'icon-user', columns: [{ text: 'ID', width: 40, sortable: true, dataIndex: 'id' }, { text: 'Email', flex: 1, sortable: true, dataIndex: 'email', field: { xtype: 'textfield' } }, { header: 'First', width: 80, sortable: true, dataIndex: 'first', field: { xtype: 'textfield' } }, { text: 'Last', width: 80, sortable: true, dataIndex: 'last', field: { xtype: 'textfield' } }], dockedItems: [{ xtype: 'toolbar', items: [{ text: 'Add', iconCls: 'icon-add', handler: function(){ // empty record store.insert(0, new Person()); rowEditing.startEdit(0, 0); } }, '-', { itemId: 'delete', text: 'Delete', iconCls: 'icon-delete', disabled: true, handler: function(){ var selection = grid.getView().getSelectionModel().getSelection()[0]; if (selection) { store.remove(selection); } } }] }] }); grid.getSelectionModel().on('selectionchange', function(selModel, selections){ grid.down('#delete').setDisabled(selections.length === 0); }); });