4
votes

Is there any reason why setupController would not get called when using {{linkTo}}? I have two instances in my app where linkTo is being used, and in the second case. It doesn't work. The only difference that I can see is that in the first case linkTo is being used in a loop, and in the second it's not. Below is relevant code for the non-working one:

App.Router.map(function() {
    this.resource("search", { path: "/search/:args" });
});

App.SearchCriteria = Ember.Object.extend({ });

App.SearchRoute = Ember.Route.extend({
    serialize: function(model, params) {
        // .. some code that converts model to a string called args
        return {'args': args}

    },
    model: function(params) {
        // convert args, which is query string-formatted, to an object
        // and then make a App.SearchCriteria object out of it.
        return App.SearchCriteria.create($.deparam(params.args));
    },
    setupController: function(controller, model) {
        controller.set("searchCriteria", model);
    }
});

In the search template:

{{view Ember.Checkbox checkedBinding="searchCriteria.music"}} Music
{{#linkTo search searchCriteria}}Search{{/linkTo}}

The last thing I see in the logs is:

Transitioned into 'search' 

Normally, I'd see the setupController being called at some point, but it's not happening or some reason. I even tried using the {{action}} method to call a handler and then use transtionTo, but that had the same results.

UPDATE 1: Adding more details

The only difference between the working and non-working cases is that in the working case, the {{linkTo}} is being called from the same template as that of the controller and router (i.e., the linkTo is in the search template and it's invoking the SearchRoute). In the working case, the linkTo is being called on the SearchRoute but from a different template belonging to a different router).

After some Chrome debugging of Ember code, I found out that the router isn't being called is because partitioned.entered is empty. In the working case, it is non-empty.

  var aborted = false;
  eachHandler(partition.entered, function(handler, context) {
    if (aborted) { return; }
    if (handler.enter) { handler.enter(); }
    setContext(handler, context);
    if (handler.setup) {
      if (false === handler.setup(context)) {
        aborted = true;
      }
    }
  });

UPDATE 2: Root issue found - bug?

I think I understand the root cause of why the handler isn't being triggered, and I think it's because the partitionHandlers(oldHandlers, newHandlers) method doesn't think that the model has changed, thus doesn't fire the handler.

To be specific, this is the relevant part of the view:

{{view Ember.Checkbox checkedBinding="searchCriteria.music"}} Music
{{#linkTo search searchCriteria}}Search{{/linkTo}}

Although the user checks off the checkbox (thus changing the state of searchCriteria), Ember doesn't think that searchCriteria is any different, thus doesn't do anything.

Is this a bug?

1
It is confusing, but the root cause is that the searchCriteria object is the same object, albeit with different contents. Since Ember is using object equality, it doesn't see this as a change. You could fix this by creating a new searchCriteria object when a param changes.Luke Melia
This is not a solution to the root issue, but it is a work-around for somebody who might need it. Along the lines of what the author of this question has mentioned, model and setupController hooks are not triggered from when using link-to or transitionTo to go to a parent route. For now, I had to create a separate route for the child and it is working.Raymond Kalonji

1 Answers

2
votes

I'm not sure what your problem is, but this may help.

setupController is called every time the route is entered. But model hook may not be called every time.

See Ember guide: http://emberjs.com/guides/routing/specifying-a-routes-model/

Note: A route with a dynamic segment will only have its model hook called when it is entered via the URL. If the route is entered through a transition (e.g. when using the link-to Handlebars helper), then a model context is already provided and the hook is not executed. Routes without dynamic segments will always execute the model hook.

Genrally speaking, if you click the link generated by link-to to enter the route, Ember will not call model hook for that route. Instead it passes the model (link-to parameter) to that route.

The philosophy here is since the client already has the model context, Ember think there is no need to get it again from server (that's model hook's job).