Riot et Backbone, combo magique?

Ma nouvelle Ă©tape dans ma dĂ©couverte de Riot est: “est-ce que ça fonctionne correctement avec Backbone?”. En effet je prĂ©fĂšre (mais ça n’engage que moi) travailler avec plusieurs “microframeworks” qu’un seul “macroframework” qui lorsqu’il disaparaĂźt ou change profondĂ©ment vous colle dans la mouise. Sans compter ma passion immodĂ©rĂ©e pour Backbone ;).

Modifions notre code serveur

Si vous ĂȘtes ici, c’est que normalement vous avez lu le post prĂ©cĂ©dent http://k33g.github.io/2015/02/02/RIOT.html

Donc modifiez le code du fichier app.js de cette façon:

var express = require('express');
var http = require('http');
var bodyParser = require('body-parser');

var app = express(), http_port = 3008;

app.use(express.static(__dirname + '/public'));

app.use(bodyParser.urlencoded({
  extended: true
}));
app.use(bodyParser.json());

/* on ajoute une mini base de données en mémoire */
var db = [
  {id: "001", firstName:"Bob", lastName:"Morane"},
  {id: "002", firstName:"John", lastName:"Doe"},
  {id: "003", firstName:"Jane", lastName:"Doe"}
];

/* envoyer la liste des humains au format json */
app.get("/humans", function(req, res) {
  res.send(db)
});

app.listen(http_port);
console.log("Listening on " + http_port);

Ajoutons les dépendances

Nous aurons besoin de:

Vous collez tout ça dans le répertoire js/vendors

votre-app/
├── public/ 
|   ├── js/ 
|   |   ├── tags/     
|   |   |    └── hello-title.tag            
|   |   └── vendors/ 
|   |        ├── backbone.js    
|   |        ├── underscore.js    
|   |        ├── jquery-2.1.3.min.js            
|   |        ├── riot.js    
|   |        └── compiler.js      
|   └── index.html
├── package.json    
└── app.js

C’est bon, nous somme prĂȘts pour continuer.

Pensez à déclarer les dépendances dans la page index.html:

<script src="js/vendors/jquery-2.1.3.js"></script>
<script src="js/vendors/riot.js"></script>
<script src="js/vendors/compiler.js"></script>
<script src="js/vendors/underscore.js"></script>
<script src="js/vendors/backbone.js"></script>

La liste des humains: version simple

Lancez déjà votre application node app.js et appelez http://localhost:3008/humans pour vérifier que vous obtenez bien un tableau de données:

[{"id":"001","firstName":"Bob","lastName":"Morane"},{"id":"002","firstName":"John","lastName":"Doe"},{"id":"003","firstName":"Jane","lastName":"Doe"}]

Dans index.html

Dans le corps de la page ajoutez le tag <humans-list></humans-list>

Au sein d’une balise <script></script> en bas de page, ajoutez le code Backbone qui va bien:

var Kind = function() {};
Kind.extend = Backbone.Model.extend;

var HumansServices = Kind.extend({
   constructor: function() {
       var Human = Backbone.Model.extend({
          urlRoot: "humans"
       });
       var Humans = Backbone.Collection.extend({model: Human, url:"humans"});

       this.humansColl = new Humans()
   }
});

var humansServices = new HumansServices();

/* Monter humans-list en lui passant le service */

riot.mount("humans-list",{
  humansServices: humansServices
});

Création du tag humans-list

Ensuite, créez un nouveau tag dans le répertoire public/js/tags que vous appelerez humans-list.tag

<humans-list>
    <div each="{humans}">
        {id} {firstName} {lastName}
    </div>

    var thatList = this;
    var humansCollection = this.opts.humansServices.humansColl;

    humansCollection.fetch().then(function() {
        thatList.humans = humansCollection.toJSON();
        thatList.update()
    });

</humans-list>

Pensez à le déclarer dans index.html:

<script src="js/tags/humans-list.tag" type="riot/tag"></script>

Et voilà, vous n’avez plus qu’à tester dans votre navigateur:

Jusque là pas de soucis, vérifions un deuxiÚme point.

La liste des humains: version “nested”

Il est intĂ©ressant parfois de ne vouloir modifier (et afficher les modifications) qu’un seul modĂšle de la liste sans avoir Ă  recharger toute la liste (surtout si elle est longue).

Nouveau tag human-card

Du coup crĂ©ons un nouveau tag dans public/js/tags que nous appellerons human-card.tag qui servira Ă  afficher le dĂ©tail d’un modĂšle:

<human-card>
    <div>{human.firstName} {human.lastName}</div>

    var thisCard = this;
    this.model = this.opts.model; /* je passe le modĂšle Backbone en options */
    this.human = this.model.toJSON()

    /* si mon modĂšle change, je mets Ă  jour l'affichage */
    this.opts.model.on("change", function(){
        thisCard.human = thisCard.model.toJSON()
        thisCard.update();
    });
    
</human-card>

Allons modifier le tag humans-list

<humans-list>
    <div each="{model, index in humans}">
        <human-card model={model}></human-card>
    </div>

    var thatList = this;
    var humansCollection = this.opts.humansServices.humansColl;

    humansCollection.fetch().then(function() {
        thatList.humans = humansCollection.models;
        thatList.update()
    });

</humans-list>

Vous avez notĂ© que l’on passe le modĂšle par le biais d’un attribut model (model n’est pas un mot clĂ©, je l’ai choisi moi mĂȘme).

Pensez à déclarer le nouveau tag dans index.html:

<script src="js/tags/human-card.tag" type="riot/tag"></script>
<script src="js/tags/humans-list.tag" type="riot/tag"></script>

Testez Ă  nouveau dans votre navigateur: vous obtiendrez la mĂȘme chose que toute Ă  l’heure, mais par contre, ouvrez la console et tapez la commande suivante:

humansServices.humansColl.at(0).set("firstName","BOBBY")

Vous prenez donc le 1er modĂšle de la collection et changez la valeur de firstName, Ă  ce moment lĂ , le trigger "change" du modĂšle est dĂ©clenchĂ© et l’affichage du modĂšle est mis Ă  jour:

Donc pour le moment, la cohabitation avec mon framework fétiche et Riot semble se passer plutÎt pas mal. Il va falloir continuer de creuser, mais je suis plutÎt optimiste.

I <3 Riot ;)

blog comments powered by Disqus

Related posts