Backbone: multiple View Models for the same model

2019-03-15 12:59发布

Newbie backbone question:

Context: Building a shopping list with backbone

I have a model class called with name, description and tags (array) properties. I would like to create two views based on this model or this model's collection.

First view will display all items like this:

<ul>
<li><h3>Item 1 Name</h3>
<p>Item 1 Description</p>
<p>Tag1, Tag2 ,Tag3</p>
</li>
.......
</ul>

Second view will display a list of tags and count of tagged items like this:

<ul>
<li>Tag1<span>{count of items tagged with tag1}</span></li>
<li>Tag2<span>{count of items tagged with tag2}</span></li>
<li>Tag3<span>{count of items tagged with tag3}</span></li>
</ul>

I built the model, collection and view to support the first view. I would like to know the right way to use the existing model (or create a new model?) to build the second view.

Thanks in advance...

existing Item model and collection (ripped from Todo.js example)

window.Item = Backbone.Model.extend({
// Default attributes for a todo item.
defaults: function() {
return {
order: Items.nextOrder()
};
}
});


window.ItemList = Backbone.Collection.extend({

model: Item,

localStorage: new Store("items"),

nextOrder: function() {
  if (!this.length) return 1;
  return this.last().get('order') + 1;
},

comparator: function(item) {
  return item.get('order');
}

});

UPDATE: Even though the overriding the parse() method works when displaying Tag names with item count, I was unable to refresh tag name/item count list after adding a new item. This may be due to the fact that the views are rendering from different collections. I will try extending the ItemList collection and overriding the parse() method. Any help is greatly appreciated.

4条回答
劫难
2楼-- · 2019-03-15 13:04

I'm pretty new to Backbone.js myself, so take this answer with a grain of salt, but I think ... you just make the second view. The whole point of de-coupling models and views is to make it so that you don't need to do anything to the models if all you want to do is do something different with your views.

So, I think you just need to create YourView2, tell it to use the same model as YourView1 and you should be in business.

查看更多
做自己的国王
3楼-- · 2019-03-15 13:04

Paul Yoder from Backbone.js google group provided the solution. You can view it here

查看更多
别忘想泡老子
4楼-- · 2019-03-15 13:06

@machineghost is right on; The models are totally decoupled from the views so you can make as many views attached to the same model as you please. You could also extend a view, if they have logic or attributes you would like to share. When I use Backbone I often find myself extending a parent view just to override the render function, or to provide a different template.

First view

ShoppingCartView = Backbone.View.extend({
  model: ShoppingCart
  ...
});

Second independent view

CheckoutView = Backbone.View.extend({
  model: ShoppingCart
  ...
});

Second view extends first

CheckoutView = ShoppingCartView.extend({ 
  template: a_different_template // syntax depends on your templating framework
  ... 
});
查看更多
一夜七次
5楼-- · 2019-03-15 13:17

After a little research, I found Collection.Parse method that seems to be right place for transforming the response after a fetch() operation. Looks like I will need a new set model, collection and view objects. This is how I implemented the parse function in my collection object. Tested successfully in Chrome. Feel free to suggest improvements

    <snip>
    parse: function(response) {

        var items = response; //the raw item model returned from localStorage  
        var tagNameItemCount = [];
        var selectedTags = ["Tag1", "Tag2", "Tag3"];
        for(i = 0; i < selectedTags.length; i++){
            var currentTagName = selectedTags[i];
            var currentItemCount = this.getItemsCountByTagName(currentTagName, items);
            tagNameItemCount.push({tagName: currentTagName, tagCount: currentItemCount});
        }

        return tagNameItemCount;



       },
getItemsCountByTagName: function (tagName, items) {
                        var taggedItems = _.filter(items, function(item){ return _.include(item.tags, tagName); });
                        return taggedItems.length;
                       },

     </snip>
查看更多
登录 后发表回答