Handling dynamic segments inside routes

Using dynamic segments and dynamic models is an important aspect of routes. The following recipe will go over how this can be accomplished.

Getting ready

Before we begin our recipes, we'll need to set up a plugin called Ember CLI Mirage. Ember plugins, also known as add-ons, make it easy to share common code between applications. The Ember CLI Mirage plugin makes it easy to create a mock server so that we can develop, test, and prototype our data. We won't cover too much of this add-on in this chapter. If you'd like more information, you can download it at https://github.com/samselikoff/ember-cli-mirage.

In this example, we'll use the Ember Data's RESTAdapter, not the new JSON API adapter.

  1. In a new project, run this installation command in the application folder:
    $ ember install [email protected]
    

    This will install version 0.1.11 of Ember CLI Mirage, Bower, and npm packages in the application. We'll be using this version for all the examples in the book.

  2. Open the config.js file in the app/mirage folder. Add a couple of new routes:
    // app/mirage/config.js
    export default function() {
    
    this.get('/students');
    this.get('/students/:id');
    }

    The first fake route, /students, will return all the student data from our Mirage in the memory database. The second fake route, /students/:id, will return only the data that matches the ID in the URL. This will be used later when we try out dynamic segments with our models.

  3. Create a new set of fixture data for students. Create a new file called students.js in the app/mirage/fixtures directory:
    // app/mirage/fixtures/students.js
    export default [
      {id: 1, name: 'Jane Smith', age: 15},
      {id: 2, name: 'Erik Hanchett', age: 14},
      {id: 3, name: 'Suzy Q', age: 17}
    ];

    This file name, students.js, matches the route and will be used to load the data in Mirages in the memory database. Be aware that Mirage also supports factories. Factories is an immensely powerful feature that makes it extremely easy to load lots of fake data. The factories can be used in test cases as well.

    For simplicity's sake, we'll just use fixture data.

  4. Load a new scenario for our application. Update the app/mirage/scenarios/default.js file:
    // app/mirage/scenarios/default.js
    export default function( server ) {
    
        server.loadFixtures();
    }

    The default.js file in the scenarios folder is used to seed the database in development. The server.loadFixtures() method loads all the fixture data so that it can be accessible to the /students route.

How to do it...

Data in our model may never change. On the other hand, that data might change many times depending on interactions with the user. This recipe will cover how to use dynamic segments with your routes and return data from the model.

  1. Begin by creating a new resource called students. Then generate an adapter named application and finally, a route:
    $ ember g resource students
    $ ember g adapter application
    $ ember g route application
    

    This will generate the routes, adapter, and template files needed for this recipe. Keep in mind that by generating the application route, you will be prompted to overwrite the application.hbs file. You can select n, for no, when this occurs.

  2. Update the router.js file with the new dynamic segment route:
    // app/router.js
    import Ember from 'ember';
    import config from './config/environment';
    
    var Router = Ember.Router.extend({
      location: config.locationType
    });
    
    Router.map(function() {
      this.route('students',  {path: '/students/:student_id'});
    });
    
    export default Router;

    This new route has a path of /students/:student_id. This route will extract :student_id from the URL and pass it to the model hook as the first argument.

    For example, let's say that we have a list of students and we wanted to be able to access each student's data by visiting /students/1 and /students/2. Each URL would then return the data for that student.

  3. Update the application.js file in the app/adapters folder:
    import DS from 'ember-data';
    
    export default DS.RESTAdapter.extend({
    });

    This will create a new RESTAdapter that Ember will use for this example. This will be covered more in the models chapter.

  4. Edit the students.js file in the app/models folder. This file is our model and will be used to retrieve data from the Mirage mock server that we created earlier:
     // app/models/student.js
    import DS from 'ember-data';
    
    export default DS.Model.extend({
        name: DS.attr('string'),
        age: DS.attr('number')
    
    });

    This creates a new model with two attributes, name and age. The model file defines what the data will look like. We'll be covering this more in the Chapter 7, Ember Models and Ember Data. For now, we will be retrieving this data from the mock server.

  5. Update the students.js file in the app/routes folder. Add the Ember Data findRecord method:
    // app/routes/students.js
    import Ember from 'ember';
    
    export default Ember.Route.extend({
        model(param) {
          return this.store.findRecord('student',param.student_id);
        }
    });

    The model hook here has one argument, param. The param argument is student_id that is passed from the route's URL. Ember Data has a findRecord method that takes two parameters. The first parameter is the name of the model and the second is the ID.

    This model will return the student record with the ID passed to it. We can now use this in our template.

  6. Edit the students.hbs file in the app/templates folder. Add the model information:
    // app/templates/students.hbs
    {{model.name}}
    {{model.age}}

    The {{model.name}} and {{model.age}} properties will retrieve the model information passed to the template from the route.

    At this point, we should be able to run ember server and see data when we access http://localhost:4200/students/1. To make things a little easier, we'll go ahead and create a new route handler for the main application route.

  7. Edit the application.js file in the app/routes folder:
    // app/routes/application.js
    import Ember from 'ember';
    
    export default Ember.Route.extend({
        model() {
          return this.store.findAll('student');
        }
    });

    Note

    Multiple models

    At times, you may want to use multiple models in one route. This can be accomplished using Ember.RSVP.hash. The hash takes parameters that return promises. When all the parameters are resolved, then Ember.RSVP.hash is resolved. In the model, it may look like this: return Ember.RSVP.hash({ students: this.store.findAll('student'), books: this.store.findAll('book')}). Each model is separated by a comma.

    This will allow our application to retrieve all the records from our student model.

  8. Open the application.hbs file in the app/templates folder. We'll add an each iterator that will link to each student's information:
    // app/templates/application.hbs
    <h2 id="title">Welcome to Chapter 4</h2>
    
    {{#each model as |student|}}
        {{#link-to 'students' student.id}}{{student.name}}{{/link-to}}<br>
    {{/each}}
    
    {{outlet}} 

    In this template, we are iterating through all the records in the student model. We are using each individual student's name as a link to our dynamic segment. The student.id argument is passed to the link-to helper.

  9. After starting the server, you'll see a list of the students and a link to each student's information. After clicking on the student's name, the student.hbs template will load with the student's information. It will look like the following image:
    How to do it...

How it works...

Dynamic models allow data to change depending on the user action. This data will depend on the dynamic segment setup in the router.js file. The segment is defined in the router file and passed from the URL to the model hook as its first argument. Ember Data uses the findRecord method to find the correct record and return it to the template so that it's available for use.

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

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