J'ai 2 modèles et une collection. JobSummary
est un modèle, JobSummaryList
est une collection d'éléments JobSummary
, puis j'ai un modèle JobSummarySnapshot
qui contient un JobSummaryList
:
JobSummary = Backbone.Model.extend({});
JobSummaryList = Backbone.Collection.extend({
model: JobSummary
});
JobSummarySnapshot = Backbone.Model.extend({
url: '/JobSummaryList',
defaults: {
pageNumber: 1,
summaryList: new JobSummaryList()
}
});
Lorsque j'appelle fetch
sur l'objet JobSummarySnapshot
, il obtient tout ... Sauf lorsque je me déplace dans la collection summaryList
, ils sont tous de type object
et pas JobSummary
.
Je suppose que cela a du sens car à part l'objet defaults
, il ne sait pas que le summaryList
doit être de type JobSummaryList
. Je peux parcourir chaque élément et le convertir en objet JobSummary
, mais j'espérais qu'il y avait un moyen de le faire sans avoir à le faire manuellement.
Voici mon code de test (fonctionne jsfiddle ici ):
var returnData = {
pageNumber: 3,
summaryList: [
{
id: 5,
name: 'name1'},
{
id: 6,
name: 'name2'}
]
};
var fakeserver = sinon.fakeServer.create();
fakeserver.respondWith('GET', '/JobSummaryList', [200,
{
'Content-Type': 'application/json'},
JSON.stringify(returnData)]);
var callback = sinon.spy();
var summarySnapshot = new JobSummarySnapshot();
summarySnapshot.bind('change', callback);
summarySnapshot.fetch();
fakeserver.respond();
var theReturnedList = callback.getCall(0).args[0].attributes.summaryList;
_.each(theReturnedList, function(item) {
console.log('Original Item: ');
console.log(item instanceof JobSummary); // IS FALSE
var convertedItem = new JobSummary(item);
console.log('converted item: ');
console.log(convertedItem instanceof JobSummary); // IS TRUE
});
MISE À JOUR: Il m'est venu à l'esprit que je pouvais remplacer la fonction d'analyse et la définir de cette façon ... J'ai ceci maintenant:
JobSummarySnapshot = Backbone.Model.extend({
url: '/JobSummaryList',
defaults: {
pageNumber: 1,
summaryList: new JobSummaryList()
},
parse: function(response) {
this.set({pageNumber: response.pageNumber});
var summaryList = new JobSummaryList();
summaryList.add(response.summaryList);
this.set({summaryList: summaryList});
}
});
Cela fonctionne jusqu'à présent. Laisser la question ouverte au cas où quelqu'un aurait un commentaire à faire ...
Votre fonction parse()
ne devrait rien set()
, c'est une meilleure pratique pour simplement renvoyer les attributs, Backbone se chargera de la définir. par exemple.
parse: function(response) {
response.summaryList = new JobSummaryList(response.summaryList);
return response;
}
Tout ce que vous retournez de parse()
est passé à set()
.
Ne rien renvoyer (ce qui revient à renvoyer undefined
) revient à appeler set(undefined)
, ce qui pourrait l'empêcher de passer la validation ou d'autres résultats inattendus si votre validate()
personnalisé/set()
s'attend à obtenir un objet. Si votre validation ou la méthode set()
échoue à cause de cela, le rappel options.success
Passé à Backbone.Model#fetch()
ne sera pas appelé.
De plus, pour rendre cela plus générique, afin que set()
vers un objet simple provenant d'autres endroits (et pas seulement à partir de la réponse du serveur) l'affecte également, vous voudrez peut-être remplacer set()
à la place:
set: function(attributes, options) {
if (attributes.summaryList !== undefined && !(attributes.summaryList instanceof JobSummaryList)) {
attributes.summaryList = new JobSummaryList(attributes.summaryList);
}
return Backbone.Model.prototype.set.call(this, attributes, options);
}
Vous pourriez également trouver Backbone-relationnel intéressant - cela facilite beaucoup le traitement des collections/modèles imbriqués dans les modèles.
edit J'ai oublié de revenir de la méthode set (), le code est maintenant mis à jour