Aurelia.io

Aurelia.io est un tout nouveau framework javascript basé sur jspm développé par l'auteur de Durandal. Ce framework est très prometteur et je suis prêt à miser sur lui en tant que prochain framework de référence front.

Le meilleur des meilleurs frameworks web

Aurelia.io propose donc un environnement de base construit autour de jspm et ES6. Il est évidemment possible d'utiliser Bower à la place de jspm et n'importe quel meta langage à la place de ES6 (coffee, typed, ou même ES5) mais il a été conçu pour ES6. Cet aspect du framework rappelle donc Dart, le langage de Google visant à remplacer Javascript par un langague plus proche de Java. On est fortement incité à utiliser un nouveau langage, qui, même s'il ne propose pas de typage fort comme Dart, propose beaucoup de nouveautés.

Au premier abord, on sent l'inspiration venir d'Angular avec ses templates et ses two-ways binding. Mais quand on y regarde de plus prêt, c'est une architecture basée sur les components à laquelle on a affaire. On y retrouve alors l'esprit de Polymer et du futur AngularJS 2.0.

Et pour finir, on va aussi retrouver un aspect d'AngularJS : l'injection de dépendances.

Simplicité du code

Je vous passe les détails du bootstraping d'une application, il vous suffira de suivre le tutorial pour en savoir plus. Allons directement voir comment sont composées les différentes parties de l'application. Ce que l'on va appeller composant est un couple viewModel/view : un fichier javascript exportant une classe et un fichier html contenant une balise <template>. Dans cette classe, on peut importer n'importe quel autre module Javascript de l'application. Depuis le template, on peut aussi importer n'importe quel composant de l'application. Nous allons regarder un exemple d'un premier composant qui va en insérer un second.

// src/welcome/welcome.js
export class Welcome{  
  constructor() {
      this.name = 'World';
  }
}
<!-- src/welcome/welcome.html -->  
<template>  
  <p>Hello ${name}!</p>
</template>  

Nous allons créer un second composant nommé welcome-button :

// src/welcome-button/welcome-button.js
export class WelcomeButton{  
  sayHello() {
      alert('Hello!!');
  }
}
<!-- src/welcome-button/welcome-button.html -->  
<template>  
  <button
    click.delegate="sayHello()">
    Hello
  </button>
</template>  

Résultat :

Et comme je vois que ce click.delegate vous intrigue, on enchaine de suite sur les bindings.

Binding

Aurelia.io nous offre non seulement une panoplie complète de binding, mais surtout, un moyen simple d'attacher une valeur à n'importe quel attribut html. Finis les ng-click, ng-submit, ng-class

Tout d'abord le binding simple, qui permet d'afficher une valeur interpolée le plus simplement du monde. La syntaxe est celle des templates strings d'ES6 : ${maVariable}. Mais on peut vouloir non seulement attacher une valeur à un attribut, mais aussi changer la façon dont cette valeur sera observée.

<label  
  class.bind="maClasse"
  style.one-time="monStyle">
  ${label}
</label>  
<input value.one-way="maVariable">  

bind est un raccourci s'adaptant au mieux au contexte : sur des contrôles de formulaire, il agira en tant que two-way binding, pour le reste, one-way. Mais comme on le voit dans cet exemple, on peut forcer le comportement. Ainsi, la valeur de mon champs est à sens unique, ce qui fait que quand je taperais du texte dans le champs, la variable associée ne sera pas mise à jour :

On va ensuite retrouver .delegate et .trigger permettant d'attacher des fonctions à des évenements simplement avec le nom de l'évenement voulu : click.delegate, submit.delegate ou mouseover.trigger par exemple.

Router

Le router est ici un service qu'on peut injecter dans n'importe quel composant et qui va donc se baser sur la route courante. On peut ainsi facilement avoir l'équivalent de ui-router, mais de façon beaucoup plus simple. Prenons un composant root qui va donc spécifier quelques routes :

// app.js
import {Router} from 'aurelia-router';  
import bootstrap from 'bootstrap';

export class App {  
  static inject() { return [Router]; }
  constructor(router) {
    this.router = router;
    this.router.configure(config => {
      config.title = 'MyApp';
      config.map([
        {
          route: ['','welcome'],
          moduleId: 'welcome/welcome',
          nav: true,
          title:'Welcome'
        },
        {
          route: 'settings',
          moduleId: 'settings/settings',
          nav: true,
          title: 'Settings'
        }
      ]);
    });
  }
}

Le module settings aura à son tour une sous navigation pour ses sections "user" et "core" :

// settings/settings.js
import {Router} from 'aurelia-router';  
import bootstrap from 'bootstrap';

export class Settings {  
  static inject() { return [Router]; }
  constructor(router) {
    this.router = router;
    this.router.configure(config => {
      config.title = 'Settings';
      config.map([
        {
          route: ['','user'],
          moduleId: 'settings/user/user',
          nav: true,
          title:'Settings user'
        },
        {
          route: ['core'],
          moduleId: 'settings/core/core',
          nav: true,
          title:'Settings core'
        }
      ]);
    });
  }
}

avec son template :

<!-- settings/settings.html -->  
<template>  
  <nav>
    <a
      repeat.for="row of router.navigation"
      class="${row.isActive ? 'active' : ''}"
      href.bind="row.href">${row.title}</a>
  </nav>
  <router-view></router-view>
</template>  

Ainsi, quand on sera sur /settings/ la vue settings/user sera affichée et sur /settings/core, ça sera la vue settings/core. C'est beaucoup plus modulable que ce que propose ui-router.
On notera que le moduleId est l'identifiant du module, qui est généralement le path vers le fichier éponyme. Ainsi, le module settings/user/user correspond au fichier "src/settings/user/user.js".

Conclusion

J'en ai déjà beaucoup dit, mais ce n'est qu'un résumé du tutoriel. Je vous invite donc à l'exporer à votre tour et l'adopter pour vos prochains projets ;)

Hadrien

Hi, I'm a french Javascript Lead Developer, Web Architect from Toulouse, France. I've worked for 12 years for many projects with YUI, AngularJS, Aurelia.io and now React and React native.

Toulouse, France https://hadrien.eu