web-dev-qa-db-fra.com

Modèle Backbone.js avec collection

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 ...

37
Bryce Fischer

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

56
shesek