Lesson 5

Routes

23

⚠️ This tutorial uses an old version of Ember. Some things might have changed!

Ember uses something called routes to decide which templates to render, what data to load, and to set up the overall application state.


The router-file (router.js) is responsible for matching up your website's URLs with your app's routes.



Let's generate our first two routes in the terminal: one for the home page, and one for the user's profile page:

Let's open the generated templates and add some markup so that we can try them out in the browser.

app/home/template.hbs
app/user/template.hbs

Alright, now go to your browser and go to localhost:4200/home and localhost:4200/user to see the results!



Now you can clearly see what that outlet-tag in the application-template is for!


Whenever the user visits a URL in your app, Ember will check if there is any route that matches the path name, and if there is, it will render its corresponding template in the {{outlet}} of the main application/template.hbs-file.


Alright, now we want to link to these pages from the navigation menu in the header.


I can haz links?


To do that, we're going to replace our boring a-tags with Ember's cool {{#link-to}}-tags, so go ahead and open up application/template.hbs again. The link-to tag takes one argument with the name of the route you want to link to:

application/template.hbs

That's all! Now you can easily navigate between the two pages by clicking on the links! One important thing to note is that the page never actually refreshes when you do so, instead, Ember dynamically replaces the template on the page and uses HTML5 History to change the URL through pure JavaScript! This makes the page a lot snappier, and is usually something that would be pretty complicated to set up manually, but with Ember we get it for free!



The router.js-file

This is all good, but what if we want to change the URL of the user-route to be localhost:4200/profile instead of localhost:4200/user? Well, let's take a closer look at the file app/router.js which links up the URLs to our routes:

app/router.js

The important part here is what's inside the Router.map()-function. Let's edit the line responsible for the user-route and specify the path that we want:

Notice now that if you go back to the browser and click on the same link, the URL will be /profile instead of /user, even though you didn't change anything in your Handlebars-template! This is because {{#link-to}} links to a route name (not a "URL name") and dynamically determines the URL, so you change the path in your router.js-file without having to update all the links in your project. Pretty neat!

Nested routes

We're not entirely done with out routes yet. If you check the mockups for the profile page, you'll see that it contains 3 "sub-parts": chirps, following and followers.


These are also links!


Wouldn't it be great if these parts had their own URLs as well? That way you could link to /user (the default) to show a user's list of chirps, /user/following to show who the user is following and /user/followers to show who the user's followers are? In Ember, this is very easy to do thanks to nested routes! Back to the terminal!

Alright, let's open up the templates and just add a simple h2-tag so that we can see them in the browser.

app/user/following/template.hbs
app/user/followers/template.hbs

Also, just like we did in the application/template.hbs-template, we need to add an {{outlet}} tag in the user-template if we want the sub-templates to appear inside it:

app/user/template.hbs

Now go to localhost:4200/profile/following or localhost:4200/profile/followers and you should see the expected HTML:



Cool! Now what about our chirps? We want those to show up as a "sub-part" on our profile page too, but without adding anything extra to the URL. To do that, we can just create a nested route called index. Ember is smart enough to understand that it should be the default.

app/user/index/template.hbs


There we go!


Let's finish off by adding some links for those nested routes as well:

app/user/template.hbs



We now have all the basic navigation of our app settled, and you should have a pretty good understanding of how Ember's routing system works. In the next chapter, we're going to look at one of the new important cornerstones of an Ember app: components!

Comments

Dhiraj Bodicherla

shouldn't it be template.hbs instead of application.hbs ?

Micha? Czy?

yes, it should be application/template.hbs for sure

Tristan Edwards

@dhirajbodicherla: @michaczy: Thanks, I forgot to fix this!

Visva DevWorks

Actually, {{#link-to}} links to the route path, if present.


As mentioned in the guide, "You can leave off the path if it is the same as the route name."

Daniel Jeffery

I think he is saying that you the text that you put in to the link-to helper is the name of a route, and not the name of the url that you would like - but I think you know that already! :p

Pavel Bastov

If you installed a separate folder for the pods as recommended here:


http://www.ember-cli.com/user-guide/#pod-structure


the application is broken at this point. You have to move the files from app/application to app/pods/application (and remove the app/application folder).

profile/avatar/default
Mauritaament

Hi. So I did what you said. However, my program seems to be dependent on both the template.hbs in the app/pods/application and app/application. If I delete either one nothing will show up in the localhost. However, keeping both I am able to get My Profile to show but not Home.

Hamzeen Hameem

<h2>{{currentPath}}</h2> also worked for me.

Jeffrey Horn

Not sure if this is a browser option, but these textareas don't fit the content in them. I'd prefer a <pre> formatted code block instead.

profile/avatar/default
Draco2003

out = our

Edem Kumodzi

I noticed that the link clicked has a little green line under the text to show it's active. Was looking through the CSS to figure out how it's doing that. Any ideas? Is this some sort of ember magic?

Tristan Edwards

@edemkumodzi: Yes, Ember automatically adds the class "active" to elements that link to the route that you are currently on. Pretty nifty! Then you can just style that class with CSS, which is what I did here.