Dynamic-Mess.com


"The world is a dynamic mess of jiggling things..."

Un tutoriel facile pour découvrir backbone.js par la pratique

Article posté le 16-10-2014 dans la catégorie Backbone.js

Afin de mettre en pratique les informations présentées dans l'article sur les bases de Backbone.js, voici un petit tutoriel basique pour commencer.

Nous allons créer une application pour gérer des tâches. Il n'y a que deux fonctions simples :
- On peut insérer une tâche
- On peut supprimer une tâche

Ce tutoriel est composé de trois parties :

  1. Explications du but de l'application
  2. Présentation du code final avec commentaires
  3. Explications sur le fonctionnement de l'application

1- Le but de l'application

Réfléchissons à la structure - graphique - de notre application.
L'ensemble sera contenu dans une div ayant pour id "ListeDeTaches".
Cette div, contiendra donc une liste au format HTML, avec les balise < ul > et < li >
A chaque ajout de tâche, nous ajouterons donc un élément encadré des balises < li >, le tout sans recharger la page bien évidemment.

Pour des raisons de simplicité pour débuter, nous n'enregistrons pas les données : donc ne rechargez par la page!

Enfin, nous mettrons un petit formulaire, pour saisir le nom de la nouvelle tâche, qui sera insérée en cas d'appui sur la touche Entrée.

Allons-y!

2- Le code de l'application

A- La partie données

//1 - Créer le model de l'objet que nous allons manipuler
var Tache = Backbone.Model.extend({
    defaults: {
        titre : 'Une tâche vide'
    }
});
//2 - Créer une collection pour manipuler les tâches
var collectionDeTaches = Backbone.Collection.extend({
    model: Tache
});

 

B- La partie Vue

Pour rappel, dans Backbone, la vue comprend aussi le contrôleur. Nous aurons donc à gérer des éléments graphiques, mais aussi des évènements.

//3 - Créer la liste
//Il s'agit d'une vue, qui prend pour paramètre la collection de tâches
var List = Backbone.View.extend({
    tagName: 'ul', //Pour la création du conteneur de la liste : balise <ul>
    // Constructeur
    initialize: function() {
        this.model.bind('add', this.ajouteObjet, this); //Ici , on réécrit la fonction ajout du modèle
        //en la remplacant par celle déclarée plus bas dans la classe, puisque c'est ici que se verront
        //les ajouts

    },
    render: function() {
        return $(this.el);//Obligatoire sinon Vue non mise à jour!
    },
    //Méthode pour gérer l'ajout d'une nouvelle tâche
    ajouteObjet: function(notreObjet) {
        $(this.el).append(new Objet({
            model: notreObjet
        }).render());
    }
});

 

//4- Créer le formulaire
//Il s'agit de la zone de saisie de la nouvelle tâche
var Form = Backbone.View.extend({
    tagName: 'form', //balise <form>
    template: _.template('<input name="titre" type="text" placeholder="Saissez le titre de la tâche"></input>'),
    initialize: function() {}, //Constructeur vide, car au chargement la liste est vide...
    render: function() {
        $(this.el).html(this.template()); //Affiche le template de l'input
        return $(this.el);//Obligatoire sinon vue non mise à jour!
    },
    events: {
        'submit': 'envoi' //Evènement par défaut pour détecter la touche entrée, et la méthode à appeler le cas échéant
    },
    envoi: function(e) {
        e.preventDefault(); //Méthode jQuery qui empêche l'appel direct de cette méthode (en fait l'action n'est pas exécutée)
        //Pour chaque ajout, on envoie tout au model
        var model = new Tache();
        _.each($(e.target).serializeArray(), function(value) {
            if (value.value !== '') {
                model.set(value.name, value.value);//Création d'une nouvelle tâche
            }
        });
        this.model.add(model); //puis on appelle la méthode "add", spécifiée dans la liste (List) déclarée précédemment
    }
});

 

//5 - La gestion des objets
// Pour rappel :
// Il s'agit d'éléments de type < li >
// On doit pouvoir les supprimer
var Objet = Backbone.View.extend({
    tagName: 'li',
    template: _.template('<%= Tache.titre %> <span id="Effacer">[Supprimer]</span>'),
    initialize: function() {
        //Constructeur vide
    },
    render: function() { //Méthode qui met en forme le message dans le template et le retourne pour affichage
        $(this.el).html(this.template({
            Tache: this.model.toJSON()
        }));
        return $(this.el);
    },
    events: { //Gestion des évènements particuliers
        'click #Effacer': 'laSuppression'
    },
    laSuppression: function() { //Fonction pour gérer la suppression
        var self = this;
        self.remove();
    }
});

 

A présent, il nous reste deux choses à faire...
Tout d'abord, il faut s'occuper de la div principale "ListeDeTaches" (nous en avons parlé plus tôt) qui doit contenir tout ce que nous venons de construire.

var TableauDesTaches = Backbone.View.extend({
    // Le constructeur (à la création de la vue) :
    initialize: function() {
        this.views = {};
        //Cette vue comprend les deux objets nécessaires : list et form
        this.views.list = new List({model: this.model});
        this.views.form = new Form({model: this.model});
    },
    // Et la méthode render
    render: function() {
        $(this.el).append(this.views.list.render()); //Demande à la liste de se générer pour affichage
        $(this.el).append(this.views.form.render()); //Idem pour le formulaire
        return $(this.el); //Obligatoire sinon vue non mise à jour!
    }
});

 

Dernière étape, et bien il faut construire tout cela!
Donc au chargement de la page, on veut :
1- Vider le contenu de la div "ListeDeTaches"
2- Y mettre notre tableau de tâches
3- Afficher tout cela

$(function () {
    $('#ListeDeTaches').html(new TableauDesTaches({
        model: new collectionDeTaches()
    }).render());
});

 

3- Explications sur le fonctionnement de l'application

Vous avez le but, le code, maintenant il vous faut quelques explications pour compléter la compréhension de l'ensemble. Je vous invite à faire le lien entre les explications et les morceaux du code concerné.

A- Au chargement de la page

Avant donc toute intervention de l'utilisateur.

  1. Première étape : au chargement de la page, nous créons un tableau des taches. Nous remarquons 2 choses:
    1. Nous lui passons en paramètre une collection de tâches
    2. On utilise le chainage : c'est à dire que dès que cela est terminé, on appelle la fonction render() du tableau des tâches. Si nous n'appelons pas cette méthode nous ne verrons rien. Nous aborderons ce point en détail plus tard, tout sera alors clair.
  2. Donc nous avons dit : création d'un tableau des tâches avec en paramètre une collection de tâches. Donc en premier, un collection d'objets de type tache est créée. Passée en paramètre au tableau des tâches (sous l'attribut model), celui ci va alors
    1. Se créer, en attribut, une nouvelle Liste en lui passant en paramètre la collection (il n'y donc qu'une seule collection dans tous le code)
    2. Faire la même chose pour le formulaire
  3. La liste, elle, modifie (bind()) la méthode add (ajout) de la collection en la remplacant avec sa méthode ajouteObjet(), et créer du coup la liste < ul >. La méthode ajouteObjet, nous y reviendrons dans la deuxième partie des explications.
  4. Le formulaire, lui, ne fait que s'occuper de créer le template de la zone de saisie des tâches. Il place un écouteur sur la touche Entrée, qui le cas échéant, appelera la méthode add() de la collection, méthode qui vient juste d'être redéfinie par la liste...
  5. Mais tout cela n'est pas encore affiché!! Quand c'est terminé, on en revient donc à la première étpae, donc à la méthode render() du tableau des tâches qui est appelée. Que fait celle-ci? Elle appelle la méthode render() de la liste et du formulaire afin de récuperer (return $(this.el)) le code HTML généré, puis l'affiche à son tour :
    1. $(this.el).append(this.views.form.render()); //Idem pour le formulaire
              return $(this.el);

Ca, c'était donc l'initialisation du système. La liste des tâches est pour l'instant vide. Passons à l'action maintenant!

B- En cas d'appui sur la touche Entrée

Ici, nous revenons au point N°4 de l'explication précédente. Le formulaire a placé un écouteur sur la touche entrée. Il a défini que le cas échant, il faudrait lancer la méthode add() de la collection. Cette méthode a été redéfinie par la liste : il s'agit de notre méthode ajouteObjet().

Donc je tape le nom d'une tâche, et valide par Entrée. L'écouteur vérifie que la tâche n'est pas vide if (value.value !== '') puis crée une nouvelle tâche en utilisant le model par défaut. Quand c'est fait, il appelle la méthode add() de la collection, donc la méthode ajouteObjet().

Cette méthode, elle prend donc en paramètre la nouvelle tâche (notre objet). Elle fait alors deux choses en une, via encore, un chainage de méthodes : elle décide d'afficher  append()  ce que va retourner la méthode render() de l'objet nouvellement créé.

Pour terminer, allons voir l'objet. Sa méthode render() affiche ($(this.el).html) le template (this.template) du nouvel objet. La méthode template récupère l'objet (donc la tâche) passé en paramètre et rempli le template avec les attributs de l'objet. Ici nous n'en avons qu'un : titre.

$(this.el).html(this.template({
            Tache: this.model.toJSON()
        }));
        return $(this.el);

Et ici le template, où on voit clairement le titre de l'objet à remplacer :

<%= Tache.titre %> <span id="Effacer">[Supprimer]</span>

Une dernière chose avec notre objet : A l'image du formulaire qui a mis un écouteur sur la touche entrée, notre objet met un écouteur de clic sur sa div ayant pour id "Effacer". A cet évènement, il dit qu'il faudra exécuter la méthode laSuppression.

'click #Effacer': 'laSuppression'

La dite méthode ayant pour but de supprimer l'objet (fonction remove()).

Voilà! Donc comme vous pouvez le constater, même pour un exemple basique sans communication avec un serveur ni stockage, il y a beaucoup de chose à savoir. On remarquera l'imbrication de JavaScript pur, de jQuery et de méthodes venues de Underscore.js. Pour tout cela, la documentation de BackBone est vitale.

Prochaine étape, améliorer notre application avec une communication avec le serveur pour stocker nos tâches!

 


Cet article vous a plu? Découvrez d'autres articles


Tweet
comments powered by Disqus