PDA

View Full Version : Need help with Ext.data.Store!



Arseny Kovalchuk
15 Mar 2010, 6:10 AM
I'm using following store:


var siteArticlesTagsStore = new Ext.data.Store({
storeId: 'tag-store',
proxy: new Ext.data.HttpProxy({
api: {
read: '/site-article-tag/list',
create: '/site-article-tag/insert',
update: '/site-article-tag/update',
destroy: '/site-article-tag/delete'
}
}),
reader: new Ext.data.JsonReader({
totalProperty: 'total',
successProperty: 'success',
idPropery: 'TAG_ID',
root: 'data',
messageProperty: 'message'},
[
{name: 'TAG_ID'},
{name: 'NAME'},
{name: 'TRANSLIT'},
{name: 'ARTICLES_COUNT'}
]
),
writer: new Ext.data.JsonWriter({
encode: true,
writeAllFields: false
}),
autoLoad: true,
autoSave: false,
listeners: {
exception : function(proxy, type, action, options, res, arg) {
if (type === 'remote') {
Ext.Msg.show({
title: '??????!',
msg: res.message,
icon: Ext.MessageBox.ERROR,
buttons: Ext.Msg.OK
});
}
}
}
});
The EditorGridPanel which uses this store looks like:


SiteArticlesTagsGrid = Ext.extend(Ext.grid.EditorGridPanel, {

initComponent : function() {
this.viewConfig = {
forceFit:true
}
this.colModel = this.getColModel();
this.selModel = this.getRowModel();
this.store = siteArticlesTagsStore;
//this.relayEvents(this.store, ['destroy', 'save', 'update']);
this.bbar = this.getPaginator();
SiteArticlesTagsGrid.superclass.initComponent.call(this);
},

getColModel: function(){
return new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
{header: "Name", dataIndex: 'NAME', editor:Ext.form.TextField},
{header: "Translit", width: 200, dataIndex: 'TRANSLIT', editor:Ext.form.TextField},
{header: "Articles count", width: 100, dataIndex: 'ARTICLES_COUNT'}
]);
},

getRowModel: function() {
return new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
rowselect: function(sm, row, rec) {
//Ext.getCmp("site-articles-tags-form").loadRecord(rec);
}
}
});
},

getPaginator: function(){
return new Ext.PagingToolbar({
store: this.store,
pageSize: 20,
displayInfo: true
});
}

});

As you can see there are two editable columns in the grid. They are "Name" and "Translit". The problem is when data in the grid is updated (the data has been changed), i am clicking the save button which simply invokes Ext.getCmp('site-articles-tags-grid').getStore().save() BUT the request is being sent to the create action, i.e to the create: '/site-article-tag/insert' url. instead of update.
Debugging shows that the record is marked as phantom but actually it is just updated!

This behavior doesn't appear when the grid is not editable. I.e. I'm not using editor in the ColumnModel.

The list action works correctly. The data is returned successfully, the sample

{"total":3,"start":"0","limit":"20","data":[{"TAG_ID":"1","NAME":"\u0434\u043e\u043c","TRANSLIT":"dom","ARTICLES_COUNT":"1"},{"TAG_ID":"2","NAME":"\u043d\u043e\u0432\u043e\u0441\u0435\u043b\u044c\u0435","TRANSLIT":"novosele","ARTICLES_COUNT":"1"},{"TAG_ID":"3","NAME":"\u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438","TRANSLIT":"tradicii","ARTICLES_COUNT":"1"}],"success":true}The each of the action simply return

{"success":false,"message":"Unsupported operation!"}Please help me recognize what I am doing wrong. I've killed the Sunday for this sh...

Any help will be appreciated!

Mike Robinson
15 Mar 2010, 6:29 AM
If you are seeing "create again," then the root cause of the problem will be your server's response to the last create-request.

ExtJS treats new records as "phantoms." When the create response comes back, it replaces the "phantom" record-IDs with real ones, and the records are no longer ghosts.

If your next request is "create" again, ExtJS still thinks they're ghosts. (It probably also thinks it has two copies of the same information.)

Arseny Kovalchuk
15 Mar 2010, 6:42 AM
No it's not a "create again" action. The problem is when the first save action is invoked. I mean the following:

1. The first time grid is activated and store is filled by the read: '/site-article-tag/list'. The data is read from DB.
2. I'm trying to edit the data and save it by store.save(). In this case the create action is invoked instead of update.

The method Ext.grid.EditorGridPanel#startEditing says that the row in the store is phantom! but it has just been loaded by "read". Is it correct?

var r = this.store.getAt(row) -- line 240 from sources of the Ext.grid.EditorGridPanel

Arseny Kovalchuk
15 Mar 2010, 8:19 AM
SOLVED after a lot of firebugging :)

idPropery: 'TAG_ID', <---- Incorrect!

Mike Robinson
15 Mar 2010, 8:59 AM
:(( Don't you just love working with a language that has no declarations to speak of? :((

Arseny Kovalchuk
15 Mar 2010, 11:47 PM
:) You are quite right. I have a lot of Java experience. I'm currently reworking a Java (JSF) project to PHP+ExtJS and sometimes it enrage me.
Thanks for you attention.

miguelconde
4 Apr 2010, 7:16 AM
What field you set in the IdProperty then?. I use a store whit the API setting and the Destroy handle dont work fine because the list record ever are being phanton. How i can handlet it to become in no phamton records?. My Server side work properly, i can save the update records, create, but when i try to delete nothing happen because the remove records think that is the phantom record and only remove it from the cache store. then, the destroy api don't run.

Arseny Kovalchuk
5 Apr 2010, 5:47 AM
What field you set in the IdProperty then?. I use a store whit the API setting and the Destroy handle dont work fine because the list record ever are being phanton. How i can handlet it to become in no phamton records?. My Server side work properly, i can save the update records, create, but when i try to delete nothing happen because the remove records think that is the phantom record and only remove it from the cache store. then, the destroy api don't run.

The issue was the fact that the property name itself was incorrect. (idPropery instead of idProperty). After the property name was fixed the code got to work correct.

In my sample 'TAG_ID' is the real id from db and it is set with list response like this

{"total":6,"limit":20,"data":[{"TAG_ID":"1","NAME":"\u0434\u043e\u043c","TRANSLIT":"dom","ARTICLES_COUNT":"2"},{"TAG_ID":"2","NAME":"\u043d\u043e\u0432\u043e\u0441\u0435\u043b\u044c\u0435","TRANSLIT":"novosele","ARTICLES_COUNT":"1"},{"TAG_ID":"3","NAME":"\u0442\u0440\u0430\u0434\u0438\u0446\u0438\u0438","TRANSLIT":"tradicii","ARTICLES_COUNT":"2"},{"TAG_ID":"4","NAME":"\u0438\u043d\u0442\u0435\u0440\u044c\u0435\u0440","TRANSLIT":"interer","ARTICLES_COUNT":"1"},{"TAG_ID":"5","NAME":"\u043a\u043e\u043c\u0444\u043e\u0440\u0442","TRANSLIT":"komfort","ARTICLES_COUNT":"1"},{"TAG_ID":"6","NAME":"\u0433\u043e\u0440\u043e\u0441\u043a\u043e\u043f","TRANSLIT":"goroskop","ARTICLES_COUNT":"1"}],"success":true}

In your case you have to check your server response on delete action. It must contain {success:true}.