Ember JS transition to nested routes where all routes are dynamic segments from a view
Asked Answered
P

1

11

We are writing an application using EmberJS. However we are still new with this framework and we're having a hard time resolving some of what may seem to be straight forward.

The model is pretty simple, there are 3 models: Queue, Task, and Image. We are using dynamic URI segments for all routes and routes for these models are nested in the form: :queue_id/:task_id/:image_id.

The routes are configured this way:

App.Router.map(function() {
   this.resource('queue', {path: ':queue_id'}, function() {
      this.resource('task', {path: ':task_id'}, function() {
         this.resource('image', {path: ':image_id'});
      });
   });
}

And somewhere in the HTML, we have this simple template to iterate through all images from a task:

{{#each task.images}}
   <li>
      {{#view App.ThumbnailView.contentBinding="this"}}
         <img {{bindAttr src="thumbnail.url"}} />
      {{/view}}
   </li>
{{/each}}

And here is the code for the Thumbnail View:

App.ThumbnailView = Ember.View.extend({
   tagName : 'a',
   click : function(e) {
       var task = //assume this value exists;
       var queue = //assume this value exists;
       var image = //assume this value exists;

       this.get('controller.target.router').transitionTo('image', queue, task, image);
   }
});

Finally, here's is our ImageRoute:

App.Image = Ember.Object.extend();
App.Image.reopenClass({
    find : function(image_id) {
       //This is where I set a breakpoint
       console.log(image_id);
    }
});

App.ImageRoute = Ember.Route.extend({
    model : function(params) {
      //image_id is the last uri segment in: #/1/1/1
      return App.Image.find(params.image_id);
    }
});

The Problem: The call to this.get('controller.target.router').transitionTo() seems to be working. I can see that when I click in one of the thumbnails view, the URL changes (e.g from /1/1/2 to something like /1/1/3). However, I'm not seeing any state change in the UI. Also, the line where I put a breakpoint doesn't seem to be triggered. But when I refresh the page, it works well.

Is there something wrong with my transition code?

Thanks.

Parma answered 10/5, 2013 at 7:8 Comment(0)
L
13

Two things to note:

First, instead of

this.get('controller.target.router').transitionTo('image', queue, task, image);

Use:

this.get('controller').transitionToRoute('image.index', queue, task, image);

This might not change the behaviour, but it's more Ember idiomatic.

The second thing is the following:

Internal transitions will not trigger the model hook on the route, because Ember assumes you are passing the model along with the transition, so no need to call the model hook since you already passed the model.

That is why your breakpoint doesn't get triggered, the find isn't being called (as it shouldn't).

I don't have enough information to find your issue but if I were to guess from the fact that a page refresh works and an internal transition doesn't is that there is an inconsistency between the objects passed to transitionTo and between what is returned from the model hook.

You should pass the exact object to transitionTo as the ones that would have been returned by themodel hook.

If you are doing:

this.get('controller').transitionToRoute('image.index', queue, task, image);

and it's not working, something is probably wrong with either queue, task, or image models you are passing.

So this:

   var task = //assume this value exists;
   var queue = //assume this value exists;
   var image = //assume this value exists;

is not very helpful because it could be where the problem is.

Lex answered 10/5, 2013 at 10:25 Comment(5)
Hi Teddy. Thanks. You are right, the model returned from the model hook is not the same as the models i am passing. Is there a way I can get the model of the ImageRoute from the ThumbnaiView?Parma
You don't need to call the actual ImageRoute model hook, you need to pass the same model as if it was returned from the model hook. You're looping over task.images, isn't this an array of App.Image model instances (same as you would return from the ImageRoute model hook)?Lex
Ok thanks. Now I think I know what to do. But since my routes are all by dynamic segments, /queue_id/task_id/image_id, does it mean i need to requery queue and task by their ids then pass those models in the transitionToRoute method? I am thinking if there is a way of getting those models without having to requery. Like for example in any route, I can use the call this.modelFor('routeName') to get the model of that route. In a view I don't think that is possible.Parma
I tried to reproduce your app here: jsfiddle.net/teddyzeenny/kZqkx hopefully it would give you some idea on how to proceed.Lex
Thanks Teddy. I'll try this first thing tomorrow morning when I get back to work..Parma

© 2022 - 2024 — McMap. All rights reserved.