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:
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.
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.
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.
18.191.254.44