Making routes dynamic

Now we have successfully returned the data fetched from the server on the invocation of a route. Let's move ahead and see how can we make our routes dynamic. Till now, the URL that maps to our routes has been fixed. There may be situations in which we may want to read parts of URL and then act according to what was received. For example, we may want to make the /products/:product_id route, which shows the product page with ID equal to :product_id, or, like in our above example, we may want to create a new route /commits/:sha to display the information of a specific commit.

The above dynamism in Ember.js routes is achieved through dynamic segments. Dynamic segments in routes start with :. Let's see this by an example. We shall continue the above example and create a new screen to link to template that shows information about a specific commit.

Let's look at the JavaScript code. First, in the router, we need to define two routes—one for complete list of the commits and one for individual detail of a specific commit:

Router.map(function(){
  this.resource("commits",function(){
    this.route("commit",{path:":sha"});
  });
});

The application router is present at example3/app/router.js

This would result in a route hierarchy that is similar to the following figure:

Making routes dynamic

Route hierarchy of the GitHub commits application

You can see that at the top level is the application route. We get the index route for free, but we are not using that route in our application, as we would focus on the commits resource here.

Now, since we created commits as a resource, we would get commits.index route automatically by the framework, which would map to the /commits/ URL.

The commit route created inside the commits resource is meant to show the details of a particular commit. As you can see in the router code, we have made this route dynamic by including the :sha dynamic segment into it:

this.route("commit",{path:":sha"});

Let us now look at the route's code:

import Ember from "ember";

export default Ember.Route.extend({
  model: function(params){
    console.log("model hook called");
    varurl = 'https://api.github.com/repos/emberjs/ember.js/commits/'+ params.sha;
    return Ember.$.getJSON(url);
  },
  serialize: function(model){
    return {sha: model.sha};
  }
});

The commits.commit dynamic route to get the information for a specific commit is present at example3/app/routes/commits/commit.js

The commits.commit route fetches the details of a particular commit that is identified by a unique SHA and returns a model that contains the commit object.

This SHA makes our route dynamic and hence we would need to handle that in our routes. For that, we would need to get the dynamic segment from the params variable that is passed on to the model method.

varurl = 'https://api.github.com/repos/emberjs/ember.js/commits/'+ params.sha;

You can see that we use params.sha to access the dynamic segment we defined in the route. Please note here that the name of the dynamic segment is the one that we defined in the router, such as the following:

this.route("commit",{path:":sha"});

We just need to omit the : to get the variable name. Let's make it more clearer by another example.

If you defined a route with dynamic route as follows:

this.route("product",{path:"/products/:category/:name"});

Here, we have defined two dynamic segments in the URL: name and category. We can access these dynamic segments in our route by using params.category and params.name variables, respectively.

Route's serialize method

Now, as we are using dynamic segment (:sha) in our commits.commit route whenever we programmatically call this route using the {{#link-to}} helper, we need a way to extract the URL params from the model object passed to the {{#link-to}} helper, so that the framework can construct the right URL for the application. The serialize method is used exactly that same purpose. This method takes in the model and returns the equivalent of the params object that can be used to generate the URLs of the given route. In our case, we would need to return an object that would have a sha property and its corresponding value.

In our template, you will see that we use the {{#link-to}} helper to link the SHA of a commit to its route:

{{#link-to 'commits.commit' c}}{{c.sha}}{{/link-to}}

When we use this link-to helper, it will use the App.CommitsCommit route's serialize method to build the dynamic URL.

If you don't return the required object from the serialize method, you would notice that the generated URL will be of the form /commits/undefined, which is not the expected behavior.

Setting up the controller

In all of the above examples, we assume that the model object that is returned from the model method of the corresponding route is automatically available in the templates. Here, we will look at how this automatic behavior is implemented in Ember.js, and if you want to change this behavior, how should you do it.

Ember.Route defines a hook that can be used to alter this default behavior. This hook is defined in the setupController method. The default implementation of setupController sets the model property of the controller. This model property is fetched from the model method in the corresponding route definition:

setupController: function(controller, model) {
  controller.set('model', model);
}

The default implementation of route's setupController function

So, if you want to set a different property than model on the controller to be accessible by the templates, you will have to change that behavior by providing your own implementation of the setupController method in your route.

There are times when you would want to add or set additional properties on the controller that maps to the route. All the additional properties changes should go in your route's setupController function:

setupController: function(controller, model) {
  this._super(controller,model);
  controller.set("myProperty","myValue");
}

You can see that we set an additional property on the controller here using controller.set.

One thing you need to be sure of is that when you provide your own implementation of setupController, the default behavior will not be executed. To keep the default behavior of setting the model property on the controller, you should call the this._super method, which will execute the Ember.RoutersetupController function and will keep the default behavior intact.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.223.206.69