Have you ever encountered a situation where the setupController function does not get called when using {{linkTo}} in Ember.js? I have noticed this issue in my application, where linkTo works fine in one instance but fails to work in another. The only distinction between the two cases seems to be that in the first scenario, linkTo is used inside a loop, while in the second case it is not. Below is the relevant code snippet for the non-working scenario:
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'
Usually, the setupController function should be called at some point during the transition, but for some reason, it is not happening. I also attempted using the {{action}} method to call a handler and then use transtionTo, but with no success.
UPDATE 1: More insights added
The key discrepancy between the working and non-working scenarios is that in the successful case, {{linkTo}} is invoked 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 contrast, in the failing case, the {{linkTo}} is being called on the SearchRoute but from a different template associated with a distinct router).
Upon debugging Ember code in Chrome, it appears that the reason the setupController is not triggered is because partitioned.entered
remains empty. In the functional case, it contains items.
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 cause identified - possible bug?
Based on my analysis, it seems like the root cause of the handler not being triggered is due to the fact that the
partitionHandlers(oldHandlers, newHandlers)
method does not recognize any changes in the model, hence the handler is not fired.
To elaborate, consider the following part of the view:
{{view Ember.Checkbox checkedBinding="searchCriteria.music"}} Music
{{#linkTo search searchCriteria}}Search{{/linkTo}}
Even though the user modifies the checkbox state (altering the searchCriteria
), Ember fails to acknowledge the change in searchCriteria
, resulting in no action being taken.
Could this be a bug in Ember.js?