je viens de faire mes premier pas avec MVC de la version 4.0
mise à part le chargement automatique des classes c'est très proche de l'implémentation MVC que j'avais faite en version 3.x
la différence fondamentale st la séparation du store et du modèle (que j'avais dans le même dossier)
autre élément de divergence je passais par le gestionnaire d'évènement pour pour activer les éléments de mes contrôler. en claire d'associé un évènement à mes actions du contrôleur et les éléments de la vue lançaient des évènements.
Ext-4.0 va un peut plus loin en distinguant ces évènement avec la notion de contrôles. le contrôleur au travers de pattern définit dynamiquement les évènements et les méthodes associées. ces pattern utilise la notation CSS ainsi il n'est plus besoin de définir de handler dans la vue référençant le contrôleur. c'est le contrôleur lui-même qui capte les évènements des objets et leur attache un listener. il conserve donc bien mieux le contrôle.
reste tout comme dans ce que j'avais fait à bien comprendre le cheminement du tout.
pour illuster mon propos je vais reprendre l'exemple fournis dans la doc. "Account Manager"
l'appli est définit dans
Code text : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 | +--app | +--controller | | +--Users.js | +--model | | +--User.js | +--store | | +--Users.js | +--view | +--user | +--List.js | +--Edit.js |
le modèle définit le type de donnée user (nom, email)
le store est le représentant local de l'espace de stokage.
les vues list et edit affiche une grille pour présenter la liste des users et edit un form pour en éditer un
et le contrôleur orchestre le tout.
voici comment les choses se passent:
à l'ouverture l'affichage de list provoque une lecture dans le store qui n'ayant pas de données en local les demandes au serveur.
de façon asynchrone lorsque les données arrives elle sont placées dans le store en se référent au modèle.
l'arrivée de données dans le modèle provoque la modification de la vue qui affiche les données.
à l'ouverture du formulaire Edit un enregistrement est lu dans le store et référencé par le formulaire.
l'utilisateur le modifie et enregistre.
le contrôleur récupère alors du form la référence de l'enregistrement ainsi que les données.
il remplace les données de l'enregistrement et demande un synchronisation du store.
les modifs sont envoyé au serveur.
dans tout ce processus chacun n'a conscience que de sa partie. c'est un gros avantage mais aussi quand on commence une difficultés. qui assure quelle fonction ?
ExtJs reste très homogène dans son approche. tout comme pour les composant graphiques, les datastores et autres éléments des version précédente c'est le mode descriptif qui est privilégié (face à une approche procédurale).
ainsi tout comme pour le reste on définit un contrôler sous la forme d'un objet de conf listant ses propriétés
Code : | Sélectionner tout |
1 2 3 4 5 6 | Ext.define('AM.controller.Users', { extend: 'Ext.app.Controller', stores: ['Users'], models: ['User'], views: ['user.List','user.Edit'], ... |
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 | Ext.define('AM.controller.Users', { extend: 'Ext.app.Controller', stores: ['Users'], models: ['User'], views: ['user.List','user.Edit'], controls:{ 'viewport > userlist': {itemdblclick: 'editUser'}, 'useredit button[action=save]': {click: 'updateUser'} }, ... |
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | Ext.define('AM.controller.Users', { extend: 'Ext.app.Controller', stores: ['Users'], models: ['User'], views: ['user.List','user.Edit'], init: function() { this.control({ 'viewport > userlist': { itemdblclick: this.editUser }, 'useredit button[action=save]': { click: this.updateUser } }); }, ... |
Code : | Sélectionner tout |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | Ext.define('AM.controller.Users', { extend: 'Ext.app.Controller', stores: ['Users'], models: ['User'], views: ['user.List','user.Edit'], init: function() { this.control({ 'viewport > userlist': { itemdblclick: this.editUser }, 'useredit button[action=save]': { click: this.updateUser } }); }, editUser: function(grid, record) { var view = Ext.widget('useredit'); view.down('form').loadRecord(record); }, updateUser: function(button) { var win = button.up('window'), form = win.down('form'), record = form.getRecord(), values = form.getValues(); record.set(values); win.close(); this.getUsersStore().sync(); } }); |
enregistrer c'est récupérer la vue, le record les données mettre les donnée dans le record fermer la vue synchroniser le store.
Un autre point que l'ont peut noter est que même si comme en version 3.x on peut référencer le store dans le composant formulaire on ne le fait pas (j'avais pris la même option)
ainsi le formulaire reste un élément d'affichage qui ne dépends de rien d'autre.
c'est le contrôleur qui assurera la liaison.
on peut tout de même utiliser la référence du store dans le form Ext-4.0 ne l’empêche pas mais alors le contrôler est by-passé. ce qui case le pattern MVC.
j'ai expérimenté avec succès, mais je ne suis pas convaincu de l'approche, l'association dynamique du store et du form. l'idée consiste à définir le form et le store de façon indépendante comme le propose MVC. puis lorsque on ouvre le form associer un store au formulaire. c'est donc bien le contrôleur qui assure la liaison. mais ensuite tout est automatique le contrôleur ne voit plus rien. je pense que même si ça demande un peu de code (très peu) il est préférable d'en rester à la façon de faire proposée dans l'exemple de Sencha.
reste un élément qui permet de démarrer tout ça. là je dois dire que Ext-4.0 fait beaucoup mieux que ce que j'avais fait.
tout comme les contrôleur Ext propose de définir une application. exactement sur le même principe un objet de conf définit les propriétés de l'application et la liste des contrôleurs.
la méthode launch est chargé de définir la vue principale de l'application (un layout plus généralement un container) elle est appelé automatiquement il n'y a rien à faire.
Je n'ai pas encore poussé le bouchon et je n'ai pas par exemple essayé comme je le fais dans mon modèle 3.x avoir un lancement qui tient compte des states de la langue etc.
il faut que je creuse pour cela les requires en effet dans un tel cas on ne peut pas démarrer les vue tant qu'on ne connait pas la langue il y a donc une phase d'init puis de start
A+JYT