How can I make sure setupController always runs?

I’m working on a documented sample page. I have a search page with a search box. Upon initiating a search, a transitionTo occurs to ‘…/search/«text»’, for example, '…/search/banana/"

I have:

  • a serialize which puts the search box text in the URL
  • a model hook which puts the URL text back in the search box.
  • a setupController hook which performs the search and places the results in the model.

However, the setupController hook isn’t always called. Right now, I have a hack in my model hook which returns the current timestamp, to make sure that Ember recognizes the model has changed and calls setupController (at least, I’m assuming that’s what happens).

Returning a timestamp seems incredibly hacky - is there a better way to make sure that setupController is called every single time?

1 Like

I assume you’re using nested routes. Nested routes were intended to be used in a scenario where the data is only loaded when the parent route is loaded the first time. setupController is not executed when routing to nested route.

I assume you ahve something like this:

App.Router.map(function(){
    this.resource('search', { path: '/search' }, function(){
        this.route('results', { path: ':keyword'} );
    });
});

You can refactor to this

App.Router.map(function(){
    this.resource('search', { path: '/search' });
    this.resource('search.results', { path: '/search/:keyword' });
});

That would run setupController every time.

Taras

At the moment, what I have is just a single resource:

App.Router.map(function() {
	this.resource('blah', { path: '/blah/:query_str' });
});

If that matches what you intended, then it doesn’t always run setupController.

It seems like if Ember believes that the model hasn’t changed, then it doesn’t run setupController?

How are you testing? Are you entering different keywords in the url and checking it will load?

Can you create a JSbin?

I’ll work on getting the file up somehow - it’s meant as an example file to begin with (so that others might be able to learn from it, and I learn as I do it). But I can explain what happens if I do not change the model in the model hook:

1. Manually visiting the URL: /blah/banana

  • the website is loaded into the browser
  • model: the search text is set on the controller for blah, based on the URL
  • setupController: the search text is read from the controller for blah, and the results stored in the model correctly.

Then with the page already loaded, manually changing the URL: /blah/orange
- the website is already loaded in the browser, so what’s in-memory is used

  • model: the search text is set on the controller for blah, based on the URL
  • setupController: «is never run by Ember»

So, this happens when the website is already loaded, but the URL is changed manually (or the refresh/history/forward/back features of the browser are used). Since the website isn’t fully reloaded, the model already exists. When a different value then isn’t returned from the model hook, Ember doesn’t think it has to run setupController (ergo my timestamp hack)

Instead of trying to get setupController to be executed(which might go against Ember idiom) you could trying binding controller’s property to route’s model property.

If you can make a jsBin( http://emberjs.jsbin.com/ ) then I can try this myself.

Here’s the JS Bin: http://emberjs.jsbin.com/oTiyiZE/1/edit

I’ve commented out the hacky bit, so it won’t work (you’ll want to view it on its own screen to be able to manually adjust the location hash). After the hacky line is uncommented, the example will work properly.

Ok, I’m going to take a look at it. I can see already that there are a few things that are complicating things.

I just want to confirm that the end goal is that you want to produce search results based on search keyword right?

I architected and wrote the code of what I think you’re asking for: https://github.com/taras/ember-search-example

Transitions all work correctly. The install instructions are in the repo.

Let me know how it goes.

Oh dear. I was barely able to comprehend what I’d written so far. I’m completely unfamiliar with github, the repo, how to use those commands, and just about everything else you’ve suddenly introduced. I would appreciate some hand-holding. :stuck_out_tongue:

ahh… no problem. I’m actually writing an article about that right now. Give me a few minutes and I’ll put together an explanation.

@dgbonomo I put together a quick explanation of how the code works embersherpa.com

I would suggest that you follow these instructions to create a emberjs.JSBin.com, that way I can take a look at it if you get stuck.

I’m also working on a few articles embersherpa.com, you can take a look at those if want to learn more.

they’re not done yet, but you might still find them useful

Thank you - I’ve tried going through the article previously, but it was too incomplete at the time. I also tried the Getting Started document for the Ember App Kit, but the documentation is just positively horrendous. Especially a Getting Started guide should really focus on step-by-step instructions, tell you what can go wrong in each step, and if you run into that, how to fix it. I hope they’ll continue to improve on the documentation and make the Ember App kit easier to use.

(I know I might sound rather ‘complainy’, but I have problems with my hands, and about two good hours of keyboard use a day even on a mechanical keyboard. It makes it doubly frustrating when things aren’t made very clear, or you run into unexpected errors that aren’t detailed in any way.)

I’ll check out your updated article soon, hopefully it will give me more insight into what’s been going on.

Might I suggest adding a “Software Requirements” section near the start? As it is, while reading, I keep finding that I need Yet Another piece of software installed and set up that I don’t have.

Aside from the App Kit your code was almost exactly what I wanted to create. I would add the following line at the top of the model hook. I have only tested it in a local file - I’ve made some adjustments to the variable names you’ve picked:

this.controllerFor('search').set('keyword', params.keyword); 

There may be a better solution, but this works. It makes sure that when you visit the URL manually (or back/forward/history/etc), the keyword ends up in the search bar.

EDIT: Also, the serialize function seems to be unnecessary at the moment?

Hi @gdbonomo,

I was away all weekend. I got rid of the Beta site and moved all incomplete articles to /wip directory on the main site. I also moved your comments over. The new url for the page that you were looking at is embersherpa.com

I integrated your feedback, it was better than the idea that I came up with.

PS: I’m a beginner too, I created Ember Sherpa for beginners to have a place to learn and find references for the kinds of projects that beginners do.

No worries. I did, however, run into an interesting issue, and I’m at a loss for how to approach it: slashes in the search text (for example, in dates). They confuse Ember. It works fine with transitions, but not so much when you adjust the URL manually. I’ve tried encoding and decoding the URL, but somewhere along the way, the %2F seems to be automatically transferred back to slashes, even before decoding - thus still confusing ember, and leaving me with yet another unsolved. I’d welcome your input.

@dgbonomo, that is an interesting one. Do you mean when the keyword with / is entered into the search field or via url?

It works fine with transitions, which happen internally. But not when using slashes via the URL.