Tutorial Ember ( Version 1.13 ) ? Part 4

By | January 12, 2016

We are made to the fourth part of this tutorial dedicated to creating a blog with Ember. We will see the creation of templates, components, and how to connect all models via the routes specified in the previous chapter. Quite a program. Let’s go!

Let us go back to our famous Routes. In the previous chapter we defined the Routes of our application. We now have to implement them. For this  a file with the name of the route can be created to link a template to its model. Luckily, we will just have to create the roads we need to change the behavior. For the rest Ember is smart enough to take care of others routes itself.

Let’s start with the module that most interests us in a blog, posts. Remember, the definition of routes for posts is as follows:

this.route('post', {path: 'post'} , function() {
 this.route('index');
 this.route('add');
 this.route('edit, {path: 'edit/:post_id'}');
 this.route('view', {path: 'edit/:post_id'});
});

Let’s start in the order with the index. This should allow us to visualize all the posts already written. Your index.js file must be in the admin/post folder.


import Ember from 'ember';

export default Ember.Route.extend({
    model : function() {
        return this.store.findAll('post');
    },
    actions : {
        add : function() {
            // Effectue la tranchions vers la route d'ajout d'un formulaire.
            this.transitionTo('admin.post.add');
        },
        deleteAll : function(posts_id) { 
            /*this.store.query('post', {'ids' : posts_id}).then(function(posts) {
                posts.forEach(function(post){
                    post.destroyRecord(); // Supprime tout les posts.
                });  

             });*/
             var that = this;
             posts_id.forEach(function(post_id){
                 that.store.findRecord('post', post_id).then(function(post) {
                    post.destroyRecord();
                 });
            });
         }
    }
});

The model method is used to load all the posts from the data source. The Actions method is a bit more complex. This method sets the response to all the actions that will be performed on the template. This method is identical to that present in the Controller. Why then define actions in routes and not in the controllers you say? The controller are relics of the first versions of Ember, These are always present for compatibility reasons and to perform some very specific actions. With Ember (1.13 – 2.x) controllers are gradually replaced by Components and Routes. In order to have no problems with future versions of Ember, I therefore advise you to define your actions in your routes.

The first action that we define is for accessing the form for adding a post . This action will be triggered by the click of a button in the template. The add  action will just make a transition to the route admin.post.add  through transitionTo method. The action deleteAll  allows  to remove all selected posts. It takes all the parameter of posts to delete, posts_id.

I put two removal methods in our delete All action. The first is more efficient because it sends only a single request containing all the IDs to retrieve the posts to be deleted from the server. But the backend must support this functionality which is not the case with our localStorage backend . So we must querying for posts one by one and remove them. This should not have any impact on performance in our case, all the operations taking place locally. In both cases, the method uses the system promise (Promise) of ember to perform an asynchronous action on the data source.

Now that our route is set, we can focus on our templates. The only currently defined template is the root template  of our application. It is called templates/application.hbs


<div class="container-fluid">
    {{outlet}}
</div>

Two things to notice here. The first is that we add a div necessary for the bootstrap styles are applied. The second is the {{outlet}} that allows us to tell to Ember the location of children templates to include. So the templates admin.hbs and public.hbs will be included in place of the {{outlet}} . The template admin.hbs is the root template of all our templates in the Admin part. It is defined like this:


<nav class="navbar navbar-light bg-faded">
    <a class="navbar-brand" href="#">Blog</a>
    <ul class="nav navbar-nav">
        <li class="nav-item active">
            <a class="nav-link" href="#">{{#link-to 'admin.post.index'}}Post{{/link-to}}<span class="sr-only">(current)</span></a>
        </li>
        <li class="nav-item">
            <a class="nav-link" href="#">{{#link-to 'admin.user.index'}}User{{/link-to}}</a>
        </li>
   </ul>
</nav>
{{outlet}}

It includes the navigation bar of the admin part and always our tag {{outlet}} which will display the child templates. We also see the {{link-to}} tag which is used to create a link to route. It takes as a parameter the name of the route to which will redirect. It remains finally the template corresponding to the route admin.post.index to display.


<div class="row">
    {{#bootstrap-table deleteAction="deleteAll" addAction="add"}}
        <table class="table table-striped table-bordered table-hover" id="posts">
            <thead>
                <tr>
                    <th>Selection</th>
                    <th>Title</th>
                    <th>User Name</th>
                    <th>Date</th>
                </tr>
            </thead>
            <tbody>
            {{#each model as |post|}}
                <tr>
                    <td>
                        <div class="checkbox">
                            <label>
                                <input type="checkbox" id="{{post.id}}" value="{{post.id}}">
                            </label>
                        </div>
                    </td>
                    <td>{{#link-to 'admin.post.edit' post}}{{post.title}}{{/link-to}}</td>
                    <td>{{post.user.name}}</td>
                    <td>{{post.date}}</td>
               </tr>
            {{/each}}
            </tbody>
        </table>
    {{/bootstrap-table}}
</div>

We have many new things in this template. The first is the presence of the tag {{bootstrap-table }} that allows as its name indicates how to create a twitter bootstrap table and especially to support actions on this table like deleting a post or selecting an element. In reality this tag is called a component. For those who already practiced Ember, components replace views and have a predominant part in Ember 2.x. The components have their own variable Scope and are quasi autonomous snippets. Their great strength is to be easily reusable anywhere in your application. Their weaknesses is some complexity to be created. In all cases when an action must be done in javascript on an item of your page, component will be required. We will see in detail in the next tutorial how to create a component and how the bootstrap-table component works.

The second {{link-to}} tag  creates a link to an action. It takes as a parameter the name of an action and possibly additional parameters to be passed in the URL. Here we passe the post or the user as params. Ember will take the object identifier to concatenate the rest of the URL. For the post we will have a url like this :  hostname:4200/admin/post/edit/:post_id.
In the next chapter we will see in detail the creation of a component with the example of the bootstrap-table component. We will also introduce the rest of the administration concerning posts.

See you soon.

 

00

2 thoughts on “Tutorial Ember ( Version 1.13 ) ? Part 4

  1. dan

    when the next chapter?
    do you have a github repo for see the tut?
    thanks for this great tut!!

    Reply
  2. scandinave Post author

    Hi dan,
    I’m busy at this time but i will do my best to post articles as soon as possible. For the Github, i don’t have one for the project at the moment, but this is a great idea.
    Thanks to reading me.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.