-
17 Feb 2011 1:19 PM #1
Nested loading / nested saving in new data package
Nested loading / nested saving in new data package
I like very much the feature called "nested loading" in the new data package and I was wondering, will there be a similar "nested saving" feature?
Assume you have a User model, which has many associated Posts. Now, when you load a user through a configured proxy you also get its posts. If the server can spell it out, the data package is smart enough to create a posts store (configured with a memory proxy I assume) in the user model.
If you modify/delete any of the posts or add a new one, and then call User.save(), will it also send the nested posts to the server? Something like this (assuming a rest/json proxy):
users.json - PUT:
Would be nice to have something like this, plus in some types of applications would be a must-have (for instance when you have to save the changes to a database in an atomic transaction).Code:{ "id": 1, "name": "John Doe", "email": "john.doe@example.com", "posts": [ { "id": 1, "message": "first post message" }, { "id": 2, "message": "second post message" }, { "id": 3, "message": "third post message" } ] }
If "nested saving" will not be provided by the API in Ext 4.0, any suggestions on how to implement such a feature in the application code?
-
19 Feb 2011 8:06 AM #2
Any idea on this?
I think this could spur an interesting discussion on how to implement transactions with the data package in ExtJS 4.0...
As a practical example, I'm planning to develop a somewhat large application (which a large number of data models) and I'm evaluating ExtJS 4.0 as THE javascript framework for it.
Suppose I have a model structure which simplified would look like this:
Each order has many items (one-to-many composition), each order item can belong to a category (one-to-one) and can also be associated with many tags (many-to-many relationship between items and tags).Code:Order \_ OrderItem --- Category \_ Tag
Order tags and categories are actually application-level catalogs and are loaded before, when the application is initialized.
Each order would have to be loaded individually, together with its associated order-items and I see no problem of doing that with Model.load(), having the server respond with a "nested" json. The user is then presented with a form to modify the loaded order and its items; order items should be modifiable/deletable; new items can also be added.
Is there a straightforward way of implementing this in an uncomplicated, RESTful manner using json/rest proxies in ExtJS 4?
I'd be thinking something like when the user presses "save", send a nested json to the server, and then have the server-side application decide what to do with the received payload, which wouldn't be difficult at all...
I imagine I could implement it by manually building the order object to save and then sending it with a low-lever ajax call, but that wouldn't be an elegant solution. A better way of doing it would be to override getRecordData() on Order model proxy.
The only thing that's missing (or I think it's missing) in order to be able to implement such a workflow in a quick and elegant way is this "nested saving" feature I was talking about.
Having this implemented in the core data API would also solve the question of how to deal with transactions; actually I think there's no point of even trying to keep track of transactions on the client-side, better have the server-side application stack decide, but for that the server has to receive the entire data "tree" in a single request.
I think that's how most people would want to use transactions anyway, wouldn't you agree?Last edited by icflorescu; 20 Feb 2011 at 7:02 AM. Reason: readability issue
-
31 May 2011 7:02 AM #3
I don't know if you found anything to solve this problem, but I'd like to share my solution.
Basically, all you need to do is define 2 additional fields in your root model and mark them as persist - {name:'viewDefinitions', persist:true}Code:Ext.define('FP.model.Definition', { extend: 'Ext.data.Model', fields: ['id', 'externalName', 'internalName', {name:'fieldDefinitions', persist:true}, {name:'viewDefinitions', persist:true} ], hasMany: [ {model: 'FP.model.FieldDefinition', name: 'fieldDefinitions'}, {model: 'FP.model.ViewDefinition', name: 'viewDefinitions'} ], proxy: { type: 'rest', url : 'data/service/', reader: { type: 'json', root: 'data' } } }); Ext.define('FP.model.FieldDefinition', { extend: 'Ext.data.Model', fields: ['id', 'type', 'internalName', 'externalName', 'description', 'defaultValue', 'valueDefinitions', 'value'], belongsTo: 'FP.model.Definition' }); Ext.define('FP.model.ViewDefinition', { extend: 'Ext.data.Model', fields: ['id', 'type', 'content'], belongsTo: 'FP.model.Definition' });
After that, once you call to Model.save() method, it will PUT all data associated with Model
-
1 Jun 2011 8:04 AM #4
try this?
try this?
I am not sure if this will help you or not, but it sure helped me accomplish something similar. Peter Muller created a patch for ExtJS-4 and Sencha Touch that will write nested JSON with parent JSON as one JSON body using a patched Ext.data.writer.Writer class (among others). His patch was intended for de-normalized databases, like CouchDB, but I don't see why it would not work for any DB server that is expecting JSON in a nested format.
Check out his thread here:
http://www.sencha.com/forum/showthre...ighlight=couch
If it is something that will work for you, please add your voice to request the patch be integrated into an official release of the data package in the future. The thread is being watched by Ed Spencer, as he is curious to see the demand. If you have issues, please post them in that thread.
Thanks.
-
13 Jun 2011 2:12 PM #5
I tried pk69com solution but it didn't work.
Although the nested field is sent in the root string, it's always empty.
Are you sure it's just setting the nested field as persist: true? This option don't even exist in the manual..
Thanks
Edit:
Actually the solution is not so hard (the one I did).
Suppose you have a model and want the grid items to be part of this model.
1 Make sure the model has proxy of type "ajax" (not rest)
2 Use the following writer in this proxy
3 Iterate over the grid to create an arrayPHP Code:writer: new Ext.data.JsonWriter({
encode: false,
writeAllFields: true,
listful: true,
root: 'data' //optional
})
4 Create a instance of the model and link the grid itemsPHP Code:var itemsArr = [];
myGrid.each(function( record ){
itemsArr.push( record.data );
});
5 Save it (using the model instance)PHP Code:var model = Ext.ModelManager.create({
Name : 'Deckard Cain',
Address : 'Tristram',
myItems : itemsArr //The model contains this item (since hasMany don't work for nested store writer submit)
}, 'MyModel');
PHP Code:model.save(); // This will send to the server an ajax request {"data":{"Name":"Deckard Cain","Address":"Tristram","myItems":[{"gridId":1,"gridItemName":"name2"},{"gridId":2,"gridItemName":"name2"}]}}
-
21 Jun 2011 7:53 AM #6
I'm doing it using the following method. Just override the getRecordData in the Json writer and set a associated property value using the associated store of the model. In the below code AssignedCategories is associated model. Note, you don't need any additional properties named AssignedCategories predefined in your base model. The below code will add the AssignedCategories property only during the post, so it will not present when access the model after the post, and that's not needed because you can access the associated items in the client side using record.AssignedCategories().
proxy: {
type: 'rest',
url: 'Catalog/Item',
reader: {
type: 'json'
},
writer: new Ext.data.JsonWriter({
encode: false,
writeAllFields: true,
listful: true,
getRecordData: function (record) {
record.set('AssignedCategories', record.AssignedCategories().data.items);
return record.data;
}
})
}
-
23 Jun 2011 5:44 AM #7
The secret seems to be the fact of overriding the JsonWriter. Even if you just return record.data without any modifications, it encodes the association data. Here's an example of a store I'm using where this is working (from this post).
Code:Ext.define('User', { extend: 'Ext.data.Model', fields: ['Id', 'Name', { name: 'HireDate', type: 'date', dateFormat: 'MS' }], hasMany: { model: 'Order', name: 'Orders' } }); Ext.define('Order', { extend: 'Ext.data.Model', fields: ['Id', { name: 'OrderDate', type: 'date', dateFormat: 'MS' }], belongsTo: 'User' }); var userStore = new Ext.data.Store({ model: 'User', proxy: { type: 'rest', url: '/Home/Save' , writer: new Ext.data.JsonWriter({ getRecordData: function(record) { return record.data; } }) } });
-
15 Jul 2011 5:56 AM #8
-
19 Jul 2011 5:52 PM #9
Hi all,
Just wanted to share a solution that works. I created a custom Json writer to override the getRecordData method metioned by several people in this thread. However, I could not get those suggestions to work as they explained. According to Extjs 4 documentation, the function getAssociatedData() in the Model does the following:
Gets all of the data from this Models loaded associations. It does this recursively - for example if we have a User which hasMany Orders, and each Order hasMany OrderItems, it will return an object like this:
orders: [
{
id: 123,
status: 'shipped',
orderItems: [
...
]
}
]
Therefore, if we override the getRecordData function of a Writer and do the following, we can achieve our goal. This is a Json writer, but the same code should work for an xml writer if someone needs it. Just create another writer and extend from the xml writer.
Ext.define('custom.writer.Json', {
extend: 'Ext.data.writer.Json',
getRecordData: function(record) {
Ext.apply(record.data,record.getAssociatedData());
return record.data;
}
});
The following is the usage:
var store = new Ext.data.Store({
model: 'User',
proxy: {
type: 'ajax',
url : '/users.json',
reader: {
type: 'json',
root: 'users'
},
writer: new custom.writer.Json({
writeAllFields: true,
root: 'users' //Optional
})
},
autoLoad: true
});
Hope this helps someone.
-
23 Sep 2011 6:48 AM #10
Thanks blee! Your custom writer really helped me figure out a way to save nested data:
http://www.sencha.com/forum/showthre...-Data&p=652277
Similar Threads
-
Loading tree data from local "nested store"
By mmix in forum Ext 3.x: Help & DiscussionReplies: 12Last Post: 24 Aug 2010, 1:39 PM -
[CLOSED-350]CheckboxGroup creates nested Panels instead of nested Containers.
By Animal in forum Ext 3.x: BugsReplies: 1Last Post: 13 Nov 2009, 12:22 PM -
Formfields wont show when in column nested in fieldset (nested in tab)
By exo in forum Ext 2.x: Help & DiscussionReplies: 2Last Post: 7 Jan 2009, 7:21 AM -
Form Layout + Nested Tab Panel + Nested BorderLayout
By pluesch0r in forum Ext 2.x: Help & DiscussionReplies: 1Last Post: 5 Feb 2008, 8:25 AM -
saving a nested tree
By notjoshing in forum Ext 1.x: Help & DiscussionReplies: 5Last Post: 16 Aug 2007, 5:36 AM


Reply With Quote