Wrap items in backbone collection?

拥有回忆 提交于 2019-12-25 02:40:07

问题


I keep running into some confusing solutions and unclear ways to wrap items that match into a div using backbone.

I am just building a simple example for myself, and would like to nest all models in a collection that have the same attribute team, using a comparator works well in organizing the list, but for the life of me I can't find a clear solution to wrapping each so that I have more control over the list of players inside the team.

There has to be a clear easy solution for a beginner like me. I really just want to keep things as clean and simple as possible. My desired html result looks like below.

<div class="pacers">
    <li>Paul</li>
    <li>Roy</li>
</div>
<div class="bulls">
    <li>Kirk</li>
    <li>Taj</li>
</div>

Based on a backbone friendly json array like below.

 [
  {
    "name": "Paul",
    "team": "pacers"
  },
  {
    "name": "Kirk",
    "team": "bulls"
  },
  {
    "firstname": "George",
    "team": "pacers"
  },
  {
    "name": "Taj",
    "team": "bulls"
  }
]

So using a comparator is awesome I just write this comparator : 'team' and it handles the list order for me, cool, but I dont have much control I would like to wrap the list in a more hierarchical system.


回答1:


Another approach:

If you are using underscore's templates this could be one way of doing it. You can use underscore's groupBy function to group the list based on teams.

var teams = [
  {
    "name": "Paul",
    "team": "pacers"
  },
  {
    "name": "Kirk",
    "team": "bulls"
  },
  {
    "firstname": "George",
    "team": "pacers"
  },
  {
    "name": "Taj",
    "team": "bulls"
  }
];
var groupedList = _.groupBy(list, function(l){
    return l.team;
});
console.log(JSON.stringify(groupedList));

This is how it would be grouped.

{
    "pacers": [
        {
            "name": "Paul",
            "team": "pacers"
        },
        {
            "firstname": "George",
            "team": "pacers"
        }
    ],
    "bulls": [
        {
            "name": "Kirk",
            "team": "bulls"
        },
        {
            "name": "Taj",
            "team": "bulls"
        }
    ]
}

You can then use for each loop and in template and generate HTML in following way. The groupedList is passed as teams to below template.

<%
   _.each(teams, function(team, teamName){
%>
   <div class="<%=teamName%>">
<%
   _.each(team, function(player){
%>
    <li><%=player.name%></li>
<%
   });
%>
    </div>
<%
   });
%>

This would generate the HTML the way you expected.

NOTE:

The code snippets are given considering underscore templating, you might have to make changes based on what you use. Hope it helps.




回答2:


Correct me if I am wrong the problem being described relates more to controlling the contents of each item in relation to it's model as well as how to simply render them in groups.

1) Niranjan has covered grouping out the data into separate lists but remember that this list returned is not a Backbone construct.

2) As per the manual the '_.groupBy' method should be available to you via the collection i.e.:

myCollection.groupBy(etc);

3) I would personally consider mapping the results of the groupBy back into models and pass each and every model into a separate view and render them from within the main list view.

var CollectionView = Backbone.View.extend({
    initialize : function () {
       // Note: I am pretending that you have a real collection.
       this.collection.fetch().then(
         this.addAll(true);
       );
    }

    addOne : function (model) {
      // call .render individual template items here for each model.
      var view = new ItemView(model);
      this.$el.append(view.render();
    },

    addAll : function (groupOpts) {
      var col = this.collection;

      if(groupOpts === true) { 
         // Do grouping (or do it in the model). Maybe put back into new collection?
      }         

      _.each(col, function(model) {
         this.addOne(model);
      }, this);
    },

    render : function () {
      // Render your template here.                    
    }
});

var ItemView = Backbone.View.extend({
   render : function () {

   }
});

Not a complete example but that's the general pattern I would follow when attempting the same thing. Having an individual view/model for each item, in my opinion, gives you more control.




回答3:


This could be handled in a pretty crazy view template (depends on your template language)... or you could use a simpler template/view and just make some more crazy collection queries (first using a pluck to get the team, de-dupping that array, then running some where's for each of the teams... but you can see how this gets crazy)

I'd vote for the view and view template should handle this... what are you using? Jade? Mustache?

Something like this - logical psuedo code here since I don't know your template language:

var team;
forEach player in players 
if(!team) {
   set team = player.team
   print open holder and then the first row
} (team !== player.team {
   set team = player.team
   print close of previous holder, then open holder and then the first row of new team
} else {
   print just the player row
}

Even so, you can see how this is a bit dirty in and of itself... but what you are describing is a view/presentation concern, and you can do it here with no new additional loops and maps and wheres (like you'd have to do if you did it in the data layer before calling the views)



来源:https://stackoverflow.com/questions/20535122/wrap-items-in-backbone-collection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!