Backbone.js – Méthode correcte de filtrage et d’affichage des données de collection dans une vue

J’ai une énorme liste de tâches chargées au départ.
Je souhaite les afficher en fonction de la liste / boîte de réception sélectionnée, afin qu’il n’y ait pas de chargement supplémentaire pour chaque liste.

window.Task = Backbone.Model.extend({}); window.TasksCollection = Backbone.Collection.extend({ model: Task, url: '/api/tasks', inbox: function() { return this.filter(function(task) { return task.get('list') == null; }); }, list: function(id) { return this.filter(function(task) { return task.get('list') == id; }); } }); window.tasks = new TasksCollection; window.TaskView = Backbone.View.extend({ tagName: 'li', template: _.template($('#item-template').html()), initialize: function() { _.bindAll(this, 'render', 'close'); this.model.bind('change', this.render); this.model.view = this; }, render: function() { $(this.el).html(this.template(this.model.toJSON())); this.setContent(); return this; }, }); window.TasksView = Backbone.View.extend({ el: '#todo-list', collection: tasks, initialize: function() { _.bindAll(this, 'render'); this.collection.bind('reset', this.render); this.collection.fetch(); }, render: function() { var t = this; $(t.el).html(''); this.collection.each(function(task) { var view = new TaskView({ model:task }); $(t.el).append( view.render().el ); }); return this; }, }); window.Nicetask = Backbone.Router.extend({ routes: { '': 'inbox', '/inbox': 'inbox', '/list/:id': 'list', }, initialize: function() { _.bindAll(this, 'inbox', 'list'); window.tasksView = new TasksView; }, inbox: function() { tasks.reset( tasks.inbox() ); }, list: function(id) { tasks.reset( tasks.list(id) ); } }); 

Ce code fonctionne, mais la fonction reset() supprime les autres tâches de la liste des tâches. Et sur un autre itinéraire, la collecte des tâches est vide.

Y a-t-il un moyen raisonnable d’y parvenir? merci pour toute idée.

ps: novice de l’épine dorsale


METTRE À JOUR

Merci à @sled et @ibjhb pour les commentaires, voici un extrait de la solution de travail.

 window.TasksView = Backbone.View.extend({ el: '#todo-list', collection: Backbone.Collection.extend(), initialize: function() { _.bindAll(this, 'render', 'addOne', 'addAll'); this.collection.bind('add', this.addOne); this.collection.bind('reset', this.render); }, render: function(data) { $(this.el).html(''); _.each(data, function(task) { this.addOne(task); }, this); return this; }, addOne: function(task) { var view = new TaskView({ model:task }); $(this.el).append( view.render().el ); }, }); window.Nicetask = Backbone.Router.extend({ routes: { '': 'inbox', '/inbox': 'inbox', '/today': 'today', '/list/:id': 'list', }, initialize: function() { _.bindAll(this, 'inbox', 'today'); window.tasksView = new TasksView; window.menuView = new MenuListView; tasks.fetch(); }, inbox: function() { tasksView.render( tasks.inbox() ); }, today: function() { tasksView.render( tasks.today() ); }, list: function(id) { tasksView.render( tasks.list(id) ); } }); 

Je pense que vous devez utiliser une autre collection. Par exemple, dans votre boîte de réception, procédez comme suit:

 inbox: function(){ currentCollection = new TasksCollection(tasks.inbox()); } 

Je n’ai pas testé cela mais quand vous faites un .reset (); vous supprimez tous vos modèles et chargez ceux qui sont passés.

@sled il y a des fautes de frappe dans le code que vous avez posté, voir les commentaires en ligne. Avez-vous posté ceci comme projet quelque part?

 // add models add: function(models, options) { // TYPO: next line was missing, so single models not handled. models = _.isArray(models) ? models.slice() : [models]; var self = this; models = _.filter(models, this.filter); // return if no models exist // TYPO: returned undefined, so was not chainable if(models.length == 0) { return this; } // actually add the models to the superset this.superset.add(models, options); return this; }, // remove models remove: function(models, options) { // TYPO: next line was missing, so single models not handled. models = _.isArray(models) ? models.slice() : [models]; // remove model from superset this.superset.remove(_.filter(_.filter(models, function(cm) { // TYPO: not 'm != null', causes error to be thrown return cm != null; }), this.filter), options); // TYPO: missing return so not chainable return this; }, 

un amendement rapide à votre solution, vous utilisez

 $(this.el).html(''); 

D’après ce que je comprends, les vues et les liaisons d’événements connexes existeront toujours dans la mémoire du navigateur. Vous devez donc idéalement utiliser view.remove () sur TaskView pour effacer correctement les liaisons d’événements ainsi que le code HTML.


Il s’agit d’un sharepoint vue légèrement différent, car j’ai cherché une solution à un problème similaire, espérant que cela pourrait aider les autres.

Mon problème: – filtrer une collection complète par atsortingbuts du modèle. par exemple. un utilisateur clique sur la vue des modèles, obtient une liste de certains atsortingbuts, sélectionne un atsortingbut qui filtre la collection pour afficher uniquement ceux ayant la même valeur.

L’itinéraire que je prends est en appelant une méthode sur la collection depuis la vue, dans mon cas, la vue est spécifique à un modèle pour:

 this.model.collection.myFilter(attr,val); 

où attr est un atsortingbut du modèle associé à la collection, alors dans le filtre quelque chose comme

 myFilter: function(attr, val){ var groupByAttr = this.groupBy(function(article){ var res = (val === undefined)? true : (article.get(attr) == val); article.set({selected:res}); return res; }); return groupByAttr; } 

J’ai utilisé ._groupBy car cela retourne 2 tableaux (positif / négatif) qui peuvent être utiles. En définissant l’atsortingbut de mode “selected”, et en le liant à la vue du modèle, je peux facilement basculer une classe qui affiche ou masque la vue.

if (val === undefined) est ajouté comme moyen simple d’effacer un filtre en appelant la même méthode sans valeur.