Question

I'm using Discourse (http://www.discourse.org/), which is built on EmberJS, and trying to observe any time the URL changes, e.g. when opening a new topic. I've seen the answer for observing the currentPath, for example here: Detect route transitions in EmberJS 1.0.0-pre.4

App.ApplicationController = Ember.Controller.extend({

  routeChanged: function(){
    // the currentPath has changed;
  }.observes('currentPath');
});

But I'm trying to detect any URL change, not just a path change. As mentioned in the comments for that answer:

This observer doesn't fire when transitioning from for example /pages/1 to /pages/2 because the path is staying the same: pages.page.index

What I'd like to do is actually detect those aforementioned transitions which don't get triggered by observes('currentPath'). Along those lines, if I do this.get('currentPath'); inside of my function, I get something like topic.fromParams but I actually am interested in the URL path e.g. /t/this-is-my-url-slug.

To put it simply, I'd like to detect when the app goes from:

/t/this-is-my-url-slug

to

/t/another-url-slug

and be able to capture the path: /t/another-url-slug

Sorry but I'm a bit of an Ember n00b and my only experience with it is through Discourse. Any ideas?

Was it helpful?

Solution 2

The solution is pretty specific to Discourse (and not as general to EmberJS), but Discourse has a URL namespace which is called for URL related functions (/components/url.js). There is a routeTo(path) function in there which gets called every time a new route is loaded. So I was able to add my own function inside of there, which ensures that:

  • my function will be called every time a Discourse route changes
  • I can capture the path itself (i.e. the URL)

OTHER TIPS

You don't need anything Ember-specific to do this. Depending on whether you are using hash or pushstate, you can use...

$(window).on('hashchange', function(){
  console.log("Hash URL is " + location.hash.substr(1));
  // Do stuff
});

or

$(window).on('popstate', function(e) {
  console.log("Hash URL is " + window.location.pathname);
  // Do stuff
});

With Luke Melia's answer you are not doing any teardown to prevent memory leaks without causing issues when using the browsers back button.

If this is needed globally for your app, and you only want to use this event to call one function, then ok. But if you want to call off() when you leave the route (which you should tear it down when you don't need it) you will cause bugs with ember. Specifically when trying to use the browsers back button.

A better approach would be to leverage the event bus and proxy the event to one that will not cause issues with the back button.

    $(window).on('hashchange', function(){ 
        //Light weight, just a trigger
        $(window).trigger('yourCustomEventName');
    });

Then When you want to listen to hash changes you listen to your custom event, then tear it down when it is not needed.

Enter Route A:

    $(window).on('yourCustomEventName', function(){ 
        // Do the heavy lifting
        functionforA();
    });

Leave Route A:

    $(window).off('yourCustomEventName');

Enter Route B:

    $(window).on('yourCustomEventName', function(){ 
        // Do the heavy lifting maybe it's different?
        functionforB();
    });

Leave Route B:

    $(window).off('yourCustomEventName');
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top