2013-01-10 25 views
11

Sto imparando Backbone.Collezione Backbone con più modelli?

Voglio creare un elenco che può contenere diversi modelli, con attributi diversi.

Ad esempio, elencando il contenuto della cartella, che potrebbe includere modelli di tipo file e modelli di cartella tipo, in qualsiasi ordine.

file : { 
    title : "", 
    date : "", 
    type : "", 
    yaddayadda : "" 
} 

folder : { 
    title : "", 
    date : "", 
    haminahamina : "" 
} 

Qual è il modo corretto di rappresentarlo in Backbone? È possibile avere una singola Collezione con più modelli?

+0

Duplicate: http://stackoverflow.com/questions/6933524/a-backbone-js-collection-of-multiple-model-subclasses/6934682#6934682 – treecoder

risposta

21

Creare un modello di base che gli altri modelli ereditano da:

var DataModel = Backbone.Model.extend({ 
    // Whatever you want in here 
}); 

var FileModel = DataModel.extend({ 
    // Whatever you want in here 
}); 

var FolderModel = DataModel.extend({ 
    // Whatever you want in here 
}); 

e rendere la model tipo di raccolta sia che lo stesso modello di base:

var DataCollection = Backbone.Collection.extend({ 
    model: DataModel 
}); 
+0

Grazie per la risposta. Quando DataCollection viene passato a una vista da rendere, come si renderà un attributo che appartiene a FileModel o FolderModel? – user1031947

+1

È sempre possibile verificare se 'obj instanceof FileModel' (o 'FolderModel') e renderizzare in modo appropriato. – Lukas

+1

Ecco come farei anche questo, ma come stai passando a DataCollection di cui stai parlando (chiamata AJAX)? In questo caso, dovrai verificare se la proprietà univoca esiste nella risposta (cioè, se (someModel.someUniqueProperty) {// esegui il rendering con una vista che gestirà tale valore di proprietà};). –

16

Si potrebbe anche farlo la spina dorsale modo. Consulta i documenti backbone collection

Fondamentalmente si creano diversi modelli aggiungendo un attributo di tie breaker dire "tipo" in questo caso.

var file = Backbone.Model.extend({ 
     defaults: { 
      // will need to include a tie breaker attribute in both models 
      type: 'file' 
     } 
    }), 
    folder = Backbone.Model.extend({ 
     defaults: { 
      // tie breaker 
      type: 'folder' 
     } 
    }); 

var fs = Backbone.Collection.extend({ 
    model: function(model, options) { 
     switch(model.type) { 
      case 'file': 
       return new file(model, options); 
       break; 
      case 'folder': 
       return new folder(model, options); 
       break; 
     } 
    } 
}); 

// after that just add models to the collection as always 
new fs([ 
    {type: 'file',name: 'file.txt'}, 
    {type: 'folder',name: 'Documents'} 
]); 
+3

mi piace questo metodo, non solo è "il backbone way" ma non richiede la logica di business extra @dennis menzionata sopra, infatti non avrai mai bisogno di alcun workaround perché funzionerà tutto come ti aspetteresti a. inoltre, credo che intendessi la riga da leggere: 'var fs = Backbone.Collection.extend ({' –

+0

Questo è un approccio molto conveniente, grazie –

+0

Si noti che questo rompe 'this.model.prototype.idAttribute', quindi dovrebbe dare un'occhiata a Maciej's [answer] (http://stackoverflow.com/a/35603643/1218980) che risolve questo problema con 'ModelFactory.prototype.idAttribute'. –

1

Backbone documention non è completa in questo caso. Non funziona se utilizzato con l'opzione merge:true e idAttribute. In questo caso è necessario:

var ModelFactory = function (attr, options) { 
    switch (attr.type) { 
    case 'file': 
     return new file(attr, options); 
    case 'folder': 
     return new folder(attr, options); 
    } 
}; 
ModelFactory.prototype.idAttribute = '_id'; 

var fs = Backbone.Model.extend({ 
    model: ModelFactory 
}); 
+0

'ModelFactory.prototype.idAttribute' è molto importante qui in quanto evita i duplicati. –

+0

Sovrascrivere la funzione' modelId' della raccolta sarebbe equivalente. –

-2
 var bannedList = app.request('rest:getBan'); 
     var whiteIpList = app.request("rest:getWhite"); 
     var whiteGroupList = app.request("rest:...."); 
     $.when(bannedList, whiteIpList, whiteGroupList). 
done(function (bannedList, whiteIpList, whiteGroupList) { 
      var collection = new Backbone.Collection(); 
      collection.add(bannedList); 
      collection.add(whiteIpList); 
      collection.add(whiteGroupList); 

     }); 


    app.reqres.setHandler("rest:getBannedList", function (data) { 
     return API.getBannedList(data); 
    }); 
    getBannedList: function (data) { 
       var user = new Backbone.Model(); 
       user.url = '/banned'; 
       user.cid = 'bannedList'; 
       var defer = $.Deferred(); 

       user.fetch({ 
        type: 'GET', 
        data: data, 
        success: function (data) { 
         defer.resolve(data); 
        }, 
        error: function (data) { 
         defer.reject(data); 
        } 
       }); 
       return defer.promise(); 
      }, 
Problemi correlati