Group binding

I am looking for a good way to snap grouped objects and display them in a grid. Here is an example of a grid:

| League / Country | Canada | United States | Brazil | | 1 | John, Sam | | Tim | | 2 | Liam | | Robert | | 3 | | James, Peter, Tom | Den | 

And the player model

 DS.Model.extend({ name: DS.attr(), country: DS.attr(), leagueId: DS.attr("number") }); 

And the data obtained from the backend:

 [ { name: "John", country: "Canada", leagueId: 1 }, { name: "Sam", country: "Canada", leagueId: 1 }, { name: "Tim", country: "Brazil", leagueId: 1 }, { name: "Liam", country: "Canada", leagueId: 2 }, ... ] 

I thought of the following:

 {{#each country in countries}} <tr> {{#each league in leagues}} <td> {{#each player in players}} {{#is player.country "==" country}} {{#is player.leagueId "==" league}} ... output player ..., eg {{ render 'player/card' player }} {{/is}} {{/is}} {{/each}} </td> {{/each}} </tr> {{/each}} 

But filtering inside the template does not look very good. Is there any way to move it to the controller?

What is the Ember-way for displaying the list of players in such a grid so that it is well attached, and if I change the country or player of the league, it is displayed in the correct cell?

+1
source share
2 answers

Follow your question in the comment:

Is there a way to have a [bound helper] as a block? So that it can be done: {{#filterByCountryAndLeague ...}} {{render 'player.card' player}}

Answer: yes and no. So how is a related helper? No. See Docs here

Related helpers do not support using Handlebars blocks or adding child views of any type.

But ... if you need to use a template to display information about each player, you can use the component instead of the associated assistant.

 App.FilteredPlayersComponent = Ember.Component.extend({ allPlayers: null, forCountry: null, forLeague: null, filteredPlayers: function(){ var allPlayers = this.get('allPlayers'); var forCountry = this.get('forCountry'); var forLeague = this.get('forLeague'); var matched = allPlayers.filterBy("country", forCountry). filterBy('leagueId', forLeague); return matched; }.property(' allPlayers.@each.country ', 'forCountry', 'forLeague') }); 

Then, inside the component template, you can render to create a specialized template for each player:

 <script type="text/x-handlebars" id="components/filtered-players"> {{#each player in filteredPlayers}} {{ render "player.card" player }} {{/each}} </script> <script type="text/x-handlebars" id="player/card"> <b>{{player.name}}</b> </script> 

Working demo here

+1
source

You can write a related helper for this as follows:

 Ember.Handlebars.registerBoundHelper('filterByCountryAndLeague', function(allPlayers, curCountry, curLeague) { var matched = allPlayers.filterBy("country", curCountry). filterBy('leagueId', curLeague); return matched.mapBy('name').join(", "); }, '@each.country', '@each.leagueId'); 

Inside the helper function, you pass all the players, as well as the current country and league that are being processed, and filter the array of allPlayers by the values ​​passed to. ( @each... at the end ensures that when a country / league update is for a player - the information is reissued.)

Then your template might look something like this:

 <table border='2'> {{! First row }} <tr> <td>League / Country</td> {{#each country in countries}} <td>{{country}}</td> {{/each}} </tr> {{! Leagues }} {{#each league in leagues}} <tr> <td>{{league}}</td> {{#each country in countries }} <td> {{ filterByCountryAndLeague model country league }} </td> {{/each}} </tr> {{/each}} </table> 

Working demo here

+1
source

Source: https://habr.com/ru/post/981471/


All Articles