Multiple dynamic segments in ember.js

My routes are currently defined as follows:

App.Router.map(function() { this.resource('players', { path: ':page_id' }, function() { this.resource('player', { path: ':player_id' }); }); }); 

The idea is that I have a list of player names on the left. The player names displayed depend on page_id. On the right, I show one player and all his information based on player_id. The fact is that both are independent, which means that I can be on the third page of the player, showing the first player on the list or not losing at all.

What I'm trying to do is something like this, which is a method in the PlayersController that gets called when I click to go to the next player page:

 doTransition: function() { var players = App.Player.findAllForPage(this.playersPerPage, this.currentOffset); players.reopen({ id: this.currentOffset }); var playerController = this.get('controllers.player'); var currentPlayer = playerController.getWithDefault('content'); if (currentPlayer) { this.transitionToRoute('player', players, currentPlayer); } else { this.transitionToRoute('players', players); } } 

What am I trying to do . When I click to go to the next page of the player, go to PlayerRoute if the player is not currently displayed, otherwise go to PlayerRoute so that the player is still displayed when the transition is performed.

Problem : sometimes the currentPlayer variable is not always zero, even if the player is not currently displayed. Is there a way around this, maybe someday get the current route?

+4
source share
2 answers

Given that you say that the two sections (the list of players based on page_id and information about the player based on player_id ) are completely independent, it seems to me that you wouldn’t nest the routes, but instead use the two named outputs (name them left and right , or page and player , etc.) that you selectively render.

Router:

 App.Router.map(function() { this.resource('page', { path: ':page_id' }); this.resource('player', { path: ':player_id' }); }); 

application.hbs:

 {{outlet page}} {{outlet player}} 

And then you can override renderTemplate for your page and player routes to render into the appropriate template. To clarify, the page route will display what you currently have as the players route (it depends on page_id, but there are many players on the page, so the route displays players based on the page), and the player route displays information about the player on based on player_id .

(As a side note, I don’t think you can invest resources the way you do right now by placing resource player under resource players - I think that only routes can be nested.)

EDIT: Using the same route with multiple dynamic segments

I think your suggestion might work. From a related example, it seems that you need to create “parent” resources (not nested routes, but having more general paths, such as / page / and / page /: page_id / player /: player_id) anyway. Then you can customize your models individually using model on the appropriate route and simply provide a serialize hook for the dual dynamic segment route:

 serialize: function(model) { return { page_id : this.modelFor('page').get('id') player_id : this.modelFor('player').get('id') }; } 

Please note: we do not rely on the model object that was transferred because you said that the page and player panels can be completely independent, so instead we use modelFor .

I think you can also handle your logic about the default page for rendering / the default player for rendering if none of them are proposed here using redirect .

Finally, you would redefine renderTemplate in your PagePlayer route to actually do the rendering:

 renderTemplate: function(model, controller) { this.render("page", { into: "page" }); this.render("player", { into: "player"}); } 

I think you should be careful not to display patterns in more general routes, because if you go from / page / 1 / player / 2 to / page / 1 / player / 3, the page route has NOT re-entered.

+5
source

While Sherwin’s answer gave me a good idea of ​​where I was going, I just wanted to give a complete example and give a general idea of ​​what I ended up with. This may help in the future.

I am going to make it simple if the models are simple int, so we have a direct translation from url to model and vice versa.

Templates:

 <script type="text/x-handlebars"> {{outlet a}} {{outlet b}} </script> <script type="text/x-handlebars" id="a"> {{model}} </script> <script type="text/x-handlebars" id="b"> {{model}} </script> 

Application:

 App = Ember.Application.create(); App.Router.map(function() { // This route has 2 dynamic segments this.resource("ab", { path: "/:a/:b" }); }); App.IndexRoute = Ember.Route.extend({ redirect: function() { // At the entry point, encapsulate the 2 models in the context object, // and transition to the route with dual dynamic segments this.transitionTo('ab', {a: 3, b:4}); } }); App.AbRoute = Ember.Route.extend({ model: function(params) { // The model is {a, b} directly return params; }, renderTemplate: function(){ // Render in the named outlet using the right controller this.render('a', {into: 'application', outlet: 'a', controller: 'a'}); this.render('b', {into: 'application', outlet: 'b', controller: 'b'}); }, serialize: function(model) { return { a: model.a, b: model.b }; }, setupController: function(controller, model) { // Setup each controller with its own model this.controllerFor('a').set('model', model.a); this.controllerFor('b').set('model', model.b); } }); 

Note:

AbController could have one “ab” rendering template {{model.a}} and {{model.b}} , but I thought the individual controllers and templates were cleaner and that it activated reuse. In addition, one of the controllers could be an ArrayController, and it would work just fine.

Js bin example

+4
source

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


All Articles