View Full Version : EditorGridPanel: autoSafe on record level

4 Aug 2009, 1:17 AM

Finally, I managed to come up with a well functioning EditorGridPanel. I then played around with the stores autoSave flag. Both, a) using an explicit save-handler and b) using autoSafe: true works just as expected.

What I'm looking for is something in between: An autoSave-mode on record level that automatically safes created/modified records as soon as they blur. This is important as the user has to fill in most of the records fields before saving makes sense at all...

I wouldn't be surprised if this has been tackled already but, unfortunately, I was not able to find a solution in the postings.

Can someone, please, point e in the right direction?

Many thanks!

4 Aug 2009, 1:29 AM
put a listener on the 'update' event of the store. Save your modified records from there. You'll have to either reload the store after the save, or manually clear the store's "modified" member so that subsequent saving doesn't resave the same records again.

4 Aug 2009, 1:54 AM
The update event is fired on a cell basis. I tried to harness the selectionchange event of the grids RowSelectionModel but it is not working correctly. If I edit a cell and immediately change to another record this last cells modification is not stored. On the other hand, when I change to another cell within the same record first and only after that I change records the modification is saved...

4 Aug 2009, 3:22 AM
Copied verbatim from the edit-grid.js file in the 3.0.0 examples:

my comment is highlighted on line 102.

* Ext JS Library 3.0.0
* Copyright(c) 2006-2009 Ext JS, LLC
* [email protected]
* http://www.extjs.com/license

function formatDate(value){
return value ? value.dateFormat('M d, Y') : '';
// shorthand alias
var fm = Ext.form;

// custom column plugin example
var checkColumn = new Ext.grid.CheckColumn({
header: 'Indoor?',
dataIndex: 'indoor',
width: 55

// the column model has information about grid columns
// dataIndex maps the column to the specific data field in
// the data store (created below)
var cm = new Ext.grid.ColumnModel([{
id: 'common',
header: 'Common Name',
dataIndex: 'common',
width: 220,
// use shorthand alias defined above
editor: new fm.TextField({
allowBlank: false
header: 'Light',
dataIndex: 'light',
width: 130,
editor: new fm.ComboBox({
typeAhead: true,
triggerAction: 'all',
lazyRender: true,
listClass: 'x-combo-list-small'
header: 'Price',
dataIndex: 'price',
width: 70,
align: 'right',
renderer: 'usMoney',
editor: new fm.NumberField({
allowBlank: false,
allowNegative: false,
maxValue: 100000
header: 'Available',
dataIndex: 'availDate',
width: 95,
renderer: formatDate,
editor: new fm.DateField({
format: 'm/d/y',
minValue: '01/01/06',
disabledDays: [0, 6],
disabledDaysText: 'Plants are not available on the weekends'

// by default columns are sortable
cm.defaultSortable = true;

// create the Data Store
var store = new Ext.data.Store({
// load remote data using HTTP
url: 'plants.xml',

// specify a XmlReader (coincides with the XML format of the returned data)
reader: new Ext.data.XmlReader(
// records will have a 'plant' tag
record: 'plant'
// use an Array of field definition objects to implicitly create a Record constructor
// the 'name' below matches the tag name to read, except 'availDate'
// which is mapped to the tag 'availability'
{name: 'common', type: 'string'},
{name: 'botanical', type: 'string'},
{name: 'light'},
{name: 'price', type: 'float'},
// dates can be automatically converted by specifying dateFormat
{name: 'availDate', mapping: 'availability', type: 'date', dateFormat: 'm/d/Y'},
{name: 'indoor', type: 'bool'}

sortInfo: {field:'common', direction:'ASC'},

listeners : {
update : function(store, record, operation){
// do your update here.


// create the editor grid
var grid = new Ext.grid.EditorGridPanel({
store: store,
cm: cm,
renderTo: 'editor-grid',
width: 600,
height: 300,
autoExpandColumn: 'common',
title: 'Edit Plants?',
frame: true,
plugins: checkColumn,
clicksToEdit: 1,
tbar: [{
text: 'Add Plant',
handler : function(){
// access the Record constructor through the grid's store
var Plant = grid.getStore().recordType;
var p = new Plant({
common: 'New Plant 1',
light: 'Mostly Shade',
price: 0,
availDate: (new Date()).clearTime(),
indoor: false
store.insert(0, p);
grid.startEditing(0, 0);

// trigger the data store load

4 Aug 2009, 3:54 AM
This is exactly how I understood your suggestion using this update event. The update event is fired after a cell editor blurs. To store data here would be the same as having set the autoSave to true. What I need is to wait for a record blur in order to update all changed fields of exactly one record with exactly one server round-trip.

Therefore, I have to set autoSave to false in order to pile up field changes. To detect the selection changes to another record I used the selectionchange event of the grids RowSelectionModel which works as well…somehow, at least.

If I simply call myGrid.store.save() on any selectionchange it won’t work in the case I’m coming from a field editor in which I made some changes. These last changes won’t be updated as the selectionchange fires before the mentioned update event of the store. The update event, however, gets the right data so it seems to have worked. But after refreshing the store this last change reverts back – it was changed after the save took place.

I suppose this is a bug (event disorder) or I really do not understand the underlying event model…

4 Aug 2009, 4:59 AM
ok, gotcha. I guess the tricky part is only determining whether it's the last edit on the record. Right?

Any chance you can use the "RowEditor" plugin? It has an 'afteredit' event that you could listen on.

4 Aug 2009, 5:30 AM
The RowEditor is not an option, no.

I guess, Ext rather should propperly update the old record first before it switches to the next one. Everything else seems quite error-prone to me...

I just remembered the stopEditing function...

selectionchange : function ( sm ) {




...but it didn't help either.