Reputation: 1470
Given is a nested model structure like this:
Model Website
+ id
+ name
+ images[] // List of Image instances
Model Image
+ imageName
+ imageUrl
A serialised version of the response looks like:
{
"id": 4711,
"name": "Some name",
"images" [
{"imageName": "Beach", "imageUrl": "http://example.com/whatever.jpg"},
...
]
}
This nested model set is persisted in a document store and is returned on request by Website.id.
There is no by-id-relation to the nested list of images, as they are persisted as a list directly in the parent model. As far as I know, the classic relations in Ext.data.Model refer to the related models via a by-id-relation.
The question is: Is there any way that I can tell the parent model to use the Image model for each of the children in it's images list?
Upvotes: 2
Views: 631
Reputation: 25001
As a first step, you can make your images data to be loaded into the model by using a field type of auto
:
Ext.define('My.Model', {
extend: 'Ext.data.Model'
,fields: [
{name: 'images', type: 'auto'}
// ... other fields
}
});
Then:
myModel.get('images');
Should return:
[
{"imageName": "Beach", "imageUrl": "http://example.com/whatever.jpg"},
...
]
From there, you should theoretically be able to implement a fully automatized solution to creates the models from this data, and -- the hardest part -- try to keep these created records and the children data in the parent model synchronized. But this is a very involved hack, and a lot of entry points in Ext code base have to be covered. As an illustration, I once tried to do that for "has one" relations, and that represent a lot of code. As a result, I never took the time to consolidate this code, and finally never used it.
I would rather advocate for a simple and local (to the model) solution. You can add a simple method to your model to get the images as records. For example:
Ext.define('My.Model', {
// ...
,getImages: function() {
var store = this.imageStore;
if (!store) {
store = new Ext.data.Store({
model: 'My.ImageModel'
,data: this.get('images') || []
});
this.imageStore = store;
}
return store;
}
});
Creating a store for the associated model will save you from having to play with the proxy and the reader. It also gives you an interface that is close to Ext's default one for associations.
If you need support for loading images more than once for the same parent record, you can hook on the field's convert
method.
Finally, you may also need to handle client-side modifications of associated data, in order to be able to save them to the server. If your associated model allows it, you could simply use the children store's sync
method (and don't forget to update the parent model's data in the sync callback!). But if your associated model isn't connected to an endpoint on the server-side, you should be able to hook on the serialize
method to save the data in the associated store (as opposed to the one stored in the parent record, that won't get updated if you work with the associated store).
Here's a last example showing both:
Ext.define('My.Model', {
extend: 'Ext.data.Model'
,fields: [
{
name: 'images'
,type: 'auto'
// enables associated data update
,convert: function(data) {
var store = this.imageStore;
if (store) {
store.loadData(data || []);
}
return data;
}
// enables saving data from the associated store
,serialize: function(value, record) {
var store = record.imageStore,
if (store) {
// care, the proxy we want is the associated model's one
var writer = store.proxy && store.proxy.writer;
if (writer) {
return Ext.Array.map(store.getRange(), function(record) {
return writer.getRecordData(record);
});
} else {
// gross implementation, simply use the records data object
return Ext.pluck(store.getRange(), 'data');
}
} else {
return record.get('images');
}
}
}
// ... other fields
}
,getImages: function() {
var store = this.imageStore;
if (!store) {
store = new Ext.data.Store({
model: 'My.ImageModel'
,data: this.get('images') || []
});
this.imageStore = store;
}
return store;
}
});
Please notice that I haven't tested this code, so it might still contains some mistakes... But I hope it will be enough to give you the general idea!
Upvotes: 2