DataGrid extJS évoluée

DataGrid extJS

Avant Propos

Ce document est un tutoriel visant à vous apprendre l'utilisation d'une datagrid extJS évoluée.

Les sources étant trop importantes pour toutes les détaillées ici, je vous conseille de télécharger le rar sur mon site : http://cv.pierrehoffmann.free.fr/extjs.php afin d'avoir le code commenté à disposition.

Ce chapitre ne détaillera que les principales fonctionnalités et composants d'une datagrid et en particulier:

  • Des colonnes triables, filtrables, masquables, déplaçables
  • Une possibilité de row-expander
  • Des informations détaillées à droite de la grid
  • Une administration complète via des boutons dans une toolbar

et accessoirement ce tutoriel décrira le fonctionnement d'une combobox dynamique, très utile pour des formulaires d'administration, et une combobox de thèmes permettant de changer le CSS à la volée.

Objectifs du tutoriel : Ce document vous permettra de savoir comment créer une datagrid extJS (une grille de données avancée) comprenant de multiples modules comme des filtres, des colonnes triables, des lignes extensibles et biens d'autres.

Notions à connaitre : extJS, Javascript, PHP, $POST, JSON

Niveau : débutant / amateur

Mots clés : extJS, datagrid, administration, JSON, Combobox dynamique, Combobox de thèmes.

Version extJS 2.2

Introduction

Ce tutoriel est bien plus long que le précédent, c'est pourquoi, par un souci de clarté, je ne vais pas développer tout le code dans ce document mais les points majeurs pour la compréhension du composant qu'est la datagrid.

Avant de commencer je vous propose de vous rendre sur http://cv.pierrehoffmann.free.fr/extjs.php afin de lancer la boite de dialogue en question et surtout de télécharger les sources afin de voir en détail les parties correspondantes.

L'archive est composée de:

Note : Les fichiers PHP form_post, form_search_utilisateur, grid-filter et log_post servent comme je l'ai expliqué de lien entre les formulaires extJS et la BDD.

Voici ce principe qui sera maintes fois utilisé au cours de ce tutoriel
Le formulaire extJS va envoyer une requête (via $POST) au fichier PHP précisé.

Le script PHP récupère ces valeurs via $POST, traite les informations en interrogeant la base de données, et écrit les résultats dans la page (via echo par exemple).
Ces résultats seront récupérés par extJS qui lira simplement ce que le script a écrit en récupérant ces données via l'outil JSON.

Afin de vous familiariser pour de bon avec ce processus, je vous invite à regarder de plus près la fonction templateSubmit dans global.js que j'utilise à de nombreuses reprises dès que je veux valider un formulaire ou interroger la bdd.

DataGrid

Préambule

La datagrid est une fonctionnalité très intéressante dans le cadre d'une gestion claire et simple d'un site web.

Ici je vais vous montrer comment en réaliser une dotée de fonctionnalités avancées (row expander, filtres...)

Création d'une DataGrid

Si vous avez suivi le précédent tutoriel, vous savez que les composants extJS ressemblent de près aux composants Swing de java, on retrouve les notions de « container » et de « component » comme la frame (fenêtre) qui contient des panels, qui contient d'autres composants, le tout de manière hiérarchique.

Ici donc, nous instancions un panel général qui contiendra tous nos autres composants.

var gridForm = new Ext.FormPanel({

Celui-ci sera découpé en 2 parties (items: [{ layout: 'column', ...) : à gauche sera la datagrid, et à droite sera un autre panel contenant lui des champs simples pour afficher les informations détaillées.

Cette partie ne décrira pas la structure des informations détaillées à droite, cependant nous verrons comment leurs passer les informations lors du click sur la ligne en récupérant l'ID du champ concerné (dans l'axe sur les combobox dynamiques).

Voyons tout d'abord de quoi est composé le contenu de la datagrid :

items: {
        xtype: 'grid',
        id: 'grid_rows',
        name: 'grid_rows',
        style:'border-left:1px solid #ccc;border-right:1px solid #ccc;',
        ds: gridStore,
        cm: colModel,
        sm: new Ext.grid.RowSelectionModel({
            singleSelect: true,
            listeners: {
                rowselect: function(sm, row, rec) {
                Ext.getCmp("form_utilisateurs").getForm().loadRecord(rec);
            }
        }
}),
plugins: [expander,filters],
    enableColLock: false,
    loadMask: true,
    border:true,
    height: 330,
    listeners: {
        render: function(g) {
        g.getSelectionModel().selectRow(0);
    },
    delay: 10 // Allow rows to be rendered.
    }
},

Détaillons ces lignes. On retrouve trois composants principaux :

  • Le DataStore (ici représenté par ds : GridStore), qui contient les données
  • Le template de chaque ligne (cm : ColModel) pour customiser chaque ligne
  • Les plugins additionnels pour ajouter des fonctionnalités à la grid.

ds: gridStore

Ds signifie DataStore, il s'agit très basiquement, d'un tableau de données (en réalité tableau des résultats retournés par la requete SQL).

//Le store qui contient les données que l'on récupere
gridStore = new Ext.data.JsonStore({
url:'grid-filter.php',
id: 'gridStore',
totalProperty: 'total',
root: 'data',
sortInfo: {field: 'id', direction: 'DESC'},
remoteSort: true,
fields: [
    {name: 'id', type:'int'},
    {name: 'nom', type:'string'},
    {name: 'prenom', type:'string'},
    {name: 'password', type:'string'},
    {name: 'email', type: 'string'},
    {name: 'rang', type: 'int'},
    {name: 'date_enregistrement',type: 'date', dateFormat: 'Y-m-d'},
    {name: 'signature', type: 'string'},
    {name: 'ip', type: 'string'}
]
});

Ici est déclaré le datastore en question et va récupérer les données via JSON dans le fichier grid-filter.php.

Il s'agit du fichier fournit par extJS.

A noter que j'ai réécris la fonction PHP JSONencode dans ce fichier car celle-ci n'est disponible de base que sous PHP5, et certains hébergeur, comme free, sont encore sous PHP4, donc c'est plus prudent ainsi.

Prenez en compte aussi que ce datastore évoluera en fonction des filtres que vous imposerez, ou des tris que vous effectuerez. (défaultsortable = true signifie que vous réinterrogerez la BDD lors du tri, dans le cas contraire vous trierais uniquement les lignes affichées dans la page du datagrid.)

cm: colModel

// La configuration type de notre tableau
var colModel = new xg.ColumnModel([
expander,
{dataIndex: 'rang', width:50, header: 'Rang',renderer: icon_etat, hidden:false},
{dataIndex: 'id', width:30, header: 'ID', renderer:cellRenderer, hidden:false},
{dataIndex: 'nom',width:100, header: 'Nom',renderer:cellRenderer, hidden:false},
{dataIndex: 'prenom',width:90,header: 'Prénom',renderer:cellRenderer, hidden:false},
{dataIndex: 'password',width:90,header: 'Password',renderer:cellRenderer, hidden:false},
{dataIndex: 'email',width:200,header: 'Email',renderer:cellRenderer, hidden:false},
{dataIndex: 'signature',width:120,header: 'Signature',renderer:cellRenderer, hidden:true},
{dataIndex: 'date_enregistrement', width:80, header: 'Date',renderer: cellDateRenderer, hidden:true},
{dataIndex: 'ip', width:60, header: 'IP du post',renderer:cellRenderer, hidden:true}
]);

Plugins

plugins: [expander,filters],

expander sert a afficher un petit résumé de la ligne lors du click sur le + à gauche de chaque ligne.

Filters sert à ajouter une fonctionnalité de recherche pour chaque colonne, qui sera bien sur cumulée pour chaque colonne filtrée, et actualisera dynamiquement la datagrid.

Finition de la DataGrid

Maintenant que la datagrid et son contenu sont créés, il reste à ajouter des éléments importants comme une barre de navigation permettant de naviguer dans les pages des résultats vu que la datagrid en montre une quantité limitée.

PagingToolbar bbar: new Ext.PagingToolbar({
    store: gridStore,
    pageSize: 10,
    plugins: filters
...

Enfin reste à implémenter une barre d'outil au dessus de la datagrid afin d'administrer celle-ci et au dessus une toolbar contenant les boutons pour gérer les utilisateurs

tbar:[
{
    text: 'Ajouter un utilisateur',
    tooltip: 'Ajouter un nouvel utilisateur',
    iconCls:'add',
    handler: ajouter_utilisateur
...

Combobox dynamique

Voici une fonctionnalité très pratique dans un site, une combobox disposant d'une auto complétion dynamique en recherchant les résultats directement dans la base de données.

new Ext.form.ComboBox({
    fieldLabel: 'Utilisateur',
    id:'comboUtilisateur',
    name:'comboUtilisateur',
    loadingText: 'Chargement en cours',
    pageSize:5,
    minChars:0,
    style:'width:90%',
    typeAhead: false,
    hideTrigger:false,
    itemSelector: 'div.search-item',
    store: utilisateurStore,
    tpl: utilisateurTemplate,
    onSelect: function(record){
    Ext.getCmp('disabledEmail').setValue(record.data.search_email);
    this.setValue(record.data.search_nom + " " + record.data.search_prenom);
    this.collapse();        
}
})

A noter donc que l'on peut surcharger la méthode de sélection d'une ligne, afin par exemple de mettre dans un champ X la valeur de la ligne sélectionnée (ce que je fais ici avec l'email).

Ensuite, deux options sont à ajouter : le template pour le design, et le store pour les données.

Pour des raisons de réutilisabilité du code, j'ai défini ces options dans global.js, car plusieurs formulaires pourraient avoir besoin d'afficher la même combobox.

//Store de la combobox dynamique permettant d'afficher dynamiquement les utilisateurs.
//Ceci va rechercher dans la bdd les utilisateurs en postant dans le fichier form_search_utilisateur
var utilisateurStore= new Ext.data.Store({
proxy: new Ext.data.HttpProxy({ url: 'form_search_utilisateur.php'}),
reader: new Ext.data.JsonReader({ root: 'users',totalProperty: 'totalCount', id: 'id'}, [
{name: 'search_id', mapping: 'search_id'},
{name: 'search_nom', mapping: 'search_nom'},
{name: 'search_prenom', mapping: 'search_prenom'},
{name: 'search_email', mapping: 'search_email'}
])
});

//Template qui sert à définir le rendu qu'aura la combobox
var utilisateurTemplate = new Ext.XTemplate(
'<tpl for="."><div class="search-item">',
'<span style="font-size:13px; font-weight:bold;"><span class="selectTitle">{search_nom}</span> - {search_prenom} </span>',
'<span style="font-size:10px;">{search_email}</span>',
'</div></tpl>'
);

Combobox de thèmes

Plusieurs designs (CSS) existent pour extJS, ici je vous propose de pouvoir les choisir dynamiquement via une combobox. Le thème changera le style complet de la page sans avoir à la recharger.

Le code se trouve dans global.js

L'idée est de créer un nouveau composant : une themebox, qui sera utilisable dans n'importe quel formulaire en utilisant ce mot clé.

Voici la déclaration de ce composant, il s'agit donc d'une extension pré remplie d'une combobox :

Ext.ux.ThemeCombo = Ext.extend(Ext.form.ComboBox, {

Pour l'ajouter dans votre formulaire, il suffit de procéder comme suit : xtype:'themecombo', (voir dans la toolbar de la datagrid)

Les différents CSS sont dans l'archive téléchargeable sur mon site. Elle contient les thèmes suivants :

  • Ext Blue Theme
  • Gray Theme
  • Dark Gray Theme
  • Slate Theme
  • Green Theme
  • Midnight Theme
  • Indigo Theme
  • Silver Cherry Theme
  • Black Theme

Conclusion

En espérant vous avoir aiguillé sur la voie du développement avec extJS.

Bon amusement !

Ce document intitulé « DataGrid extJS évoluée » issu de CodeS SourceS (codes-sources.commentcamarche.net) est mis à disposition sous les termes de la licence Creative Commons. Vous pouvez copier, modifier des copies de cette page, dans les conditions fixées par la licence, tant que cette note apparaît clairement.
Rejoignez-nous