Pagination dans une grille extjs (Ext.grid.GridPanel) avec des données JSON provenant d’un service WCF#

Dans cet article on va partir de la grille basique qu’on a construit dans l’article précédent et on va lui rajouter la pagination. On peut donc reprendre tout le code et avant de rentrer dans le vif du sujet on va changer la méthode de la requête http au web service de POST en GET dans l’objet HttpProxy, comme ceci :

var myProxy = new Ext.data.HttpProxy({
    url: 'http://localhost/pagedgrid/serveur/Person.svc/Get',
    method: 'GET'
    
});

Bien évidemment et par voie de conséquence on doit aussi changer le service pour accepter les requêtes GET, il suffit alors de changer le tag WebInvoke en WebGet. (Le code du service est joint ci-dessous).

Vous vous demandez certainement : « Mais pourquoi il change le POST en GET ? » Tout simplement parce que la PagingToolbar a quelques problèmes à fonctionner avec la méthode POST et il faut faire un Workaround en introduisant les extensions pour que ça marche. Même si la solution est connue je préfère commencer avec la solution la plus simple pour que vous ne soyez pas confus.

Maintenant que tout ça est fait, on va commencer les choses sérieuses. Il s’agit donc de rajouter en bas du tableau une barre de pagination. Pour ce faire, on va utiliser une classe toute prête qui s’appelle Ext.PagingToolbar qui permet de faire de la pagination. Cette classe prend en paramètre

- la taille de la page (par défaut c’est égal à 20)

- le store lui permettant de ramener les données

Le store va ramener des données avec un total, la paging toolbar va alors :

- Calculer le nombre de pages

- Se positionner à la première page

Et à chaque fois qu’on va cliquer sur le bouton « Page suivante » la paging toolbar va consulter le store pour avoir les données de la page suivante en concaténant aux paramètres de la requête http deux paramètres :

- start : l’index du premier enregistrement de la page suivante (commence à zéro)

- limit : la taille de la page

Pour inclure la Paging toolbar dans le GridPanel, il y a la configOption bbar (Bottom bar) qui permet d’insérer une barre située en bas du tableau en opposition à tbar (toolbar) qui elle est positionée en haut du tableau. Voici le bout de code à ajouter à votre GridPanel pour ajouter la pagination :

bbar: new Ext.PagingToolbar({
    pageSize: 5,
    store: store
}),

L’objet GridPanel devient alors :

var gr = new Ext.grid.GridPanel({
    el: 'grid', //div dans la quelle le GridPanel sera dessiné
    viewConfig: { //Fait en sorte que la somme des largeurs de colonnes soit égale à la taille de la grille
        forceFit: true
    },
    ds: store, // la source de données
    cm: new Ext.grid.ColumnModel([ //Définit les colonnes du tableau et le mapping avec les champ du Record
        {header: "Nom", width: 120, sortable: true, dataIndex: 'nom' },
        { header: "Prenom", width: 100, sortable: true, dataIndex: 'prenom' }
    ]),
    sm: new Ext.grid.RowSelectionModel({ singleSelect: true }), // Politique de séléction de ligne (Sélection simple)
    width: 600, //largeur de la grille
    height: 300, //hauteur de la grille
    frame: true, //dessine la grille avec un contour arrondit
    bbar: new Ext.PagingToolbar({
        pageSize: 5,
        store: store
    }),
    title: 'Grid Panel Example' //titre de la grille

});

Donc tout ce que fait la paging toolbar c’est nous préparer le terrain pour faire de la pagination. Il nous reste du travail à faire côté serveur pour ramener les bonnes données puisqu’il faut que mon service accepte les deux paramètres start et limit envoyés par la paging toolbar et renvoyer les données en conséquence. (Vous trouverez ci-joint le code du service modifié)

La paging toolbar n’envoie pas les paramètres start et limit à l’initialisation du tableau, donc il faut bien faire attention de les initialiser au load du store de la manière suivante :

store.load({params: {start:0, limit:5}});

Ces deux paramètres seront écrasés dans la requête http par ceux envoyés par la paging toolbar à chaque changement de page.

Voici le résultat en utilisant les mêmes données que l’article précédent:

image

En ce qui concerne l’utilisation de la paging toolbar avec la méthode POST, je publierais bientôt un article qui explique le problème qui se pose et la solution proposée.

Code côté client (Javascript) 

Extjs | Javascript | WCF
Friday, March 20, 2009 10:23:34 PM (Romance Standard Time, UTC+01:00) #    Comments [0]  | 

 

Remplir une grille extjs (Ext.grid.GridPanel) avec des données JSON provenant d’un service WCF#

Il existe plusieurs façons de remplir une grille, dans cet article on va attaquer un service WCF pour récupérer les données à l’aide de la classe Ext.data.Store et les lier à un GridPanel.

Mon service WCF me renvoie une liste de personnes contenant leurs noms et prénoms en format JSON. Il me renvoie aussi avec cette liste le nombre total de personnes contenues dans la réponse. Cette information est optionnelle et inutile pour notre cas mais elle peut s’avérer très utile dans d’autres cas comme pour la pagination par exemple.

Voici un exemple de réponse du service :

{"list":
    [
        {"nom":"Plat","prenom":"Jérémie"},
        {"nom":"Nemili","prenom":"Mohamed Zied"},
        {"nom":"Nemili","prenom":"Walid"},
        {"nom":"Marbre","prenom":"Jean-Pierre"},
        {"nom":"Mini","prenom":"Christophe"},
        {"nom":"Nemili","prenom":"Anas"},
        {"nom":"Dupont","prenom":"Jérôme"},
        {"nom":"Delalettre","prenom":"Emilie"},
        {"nom":"Dubois","prenom":"Francine"},
        {"nom":"Charde","prenom":"François"},
        {"nom":"Picq","prenom":"Laurent"},
        {"nom":"Azafrar","prenom":"Abdelkarim"},
        {"nom":"Nemili","prenom":"Hajer"},
        {"nom":"Carvalho","prenom":"Rui"},
        {"nom":"Foutard","prenom":"Jean-Marie"},
        {"nom":"Othmani","prenom":"Idriss"}
    ],
    "total":16
}

On remarque que les données sont encapsulées dans un objet racine appelé « list » , il existe plusieurs raisons à cela :

- Le composant Ext.data.Store qu’on va utiliser plus tard a besoin qu’on lui spécifie la racine des données.

- Si on met les données en vrac, c'est-à-dire sans racine, on ne pourrait pas mettre toutes les autres propriétés comme la propriété « total » ou eventuellement la propriété « id » qui indique le champ qui représente l’id dans la collection de données.

On se rend compte donc que la librairie Extjs impose un certain formatage des données ce qui doit être pris en compte très tôt dans la conception de l’architecture de votre application.

Du côté client, on va commencer par initialiser une page html « Extjs enabled » en ajoutant les rééfrences vers les fichiers js qu’il faut bien (voir cet article)

Ensuite, dans le body de la page on ajouter un div avec l’id « grid » et un lien vers une page Javascript vide dans le haeder (ici testfile.js). Voici la page html complète :

 

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
    <title>test page</title>
    <script type="text/javascript" src="../../ext-2.2.1/adapter/ext/ext-base.js"></script>
    <!--script type="text/javascript" src="../../ext-2.2.1/ext-all.js"></script-->

    <script src="../../ext-2.2.1/ext-all-debug.js" type="text/javascript"></script>
    <script type="text/javascript" src="./testfile.js"></script>
    
    <link rel="stylesheet" type="text/css" href="../../ext-2.2.1/resources/css/ext-all.css"/>
    <link rel="stylesheet" type="text/css" href="../../css/Main.css"/>    
</head>
<body>
    <div id="grid"></div>
</body>
</html>

Pour peupler une grille on a besoin de :

- Une instance de la classe Ext.data.Record qui nous permet de définir la structure des lignes de données qu’on va afficher dans la grille et provenant du service web. Pour notre exemple, on a deux champs : nom et prenom. Pour instancier un objet de type Ext.data.Record il est conseillé d’utiliser la méthode « create » qui permet de renvoyer une nouvelle instance au lieu du constructeur.

var personne = Ext.data.Record.create([
    { name: 'nom' }, 
    {name: 'prenom'}
]);

- Un reader permettant de créer un tableau d’objets de type « Ext.data.Record » à partir des données provenant du service web. Pour cela, il faut définir le nœud racine des données avec la propriété « root ». La structure d’un enregistrement en passant un objet de type « Ext.data.Record ». On peut aussi définir de manière optionnelle la propriété de l’objet récupéré du web service qui correspond au nombre total d’enregistrements qu’on va afficher dans la grille à l’aide de la propriété « totalProperty » ou encore la propriété de l’enregistrement qui correspond à l’id.

var myReader = new Ext.data.JsonReader({
    totalProperty: "total",
    root: "list"

}, personne
);

- Une instance de HttpProxy qui permet de lire des données à partir d’une URL.

var myProxy = new Ext.data.HttpProxy({
    url: 'http://localhost/simplegrid/serveur/Person.svc/Get',
    method: 'POST'
    //params: {}
});

- Enfin une instance de Ext.data.Store est l’équivalent de l’objet DataSource en ASP.NET, le store fournit les données pour les composants UI comme le ComboBox, GridPanel, … Pour instancier un Store

var store = new Ext.data.Store(
    {
        proxy: myProxy,
        reader: myReader

    }
);

Une fois on a une instance de Store, on instancie le GridPanel de la manière suivante :

var gr = new Ext.grid.GridPanel({
    el: 'grid', //div dans la quelle le GridPanel sera dessiné
    viewConfig: { //Fait en sorte que la somme des largeurs de colonnes soit égale à la taille de la grille
        forceFit: true
    },
    ds: store, // la source de données
    cm: new Ext.grid.ColumnModel([ //Définit les colonnes du tableau et le mapping avec les champ du Record
        {header: "Nom", width: 120, sortable: true, dataIndex: 'nom' },
        {header: "Prenom", width: 100, sortable: true, dataIndex: 'prenom' }
    ]),
    sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),// Politique de séléction de ligne (Sélection simple)
    width: 600, //largeur de la grille
    height: 300, //hauteur de la grille
    frame: true, //dessine la grille avec un contour arrondit
    title: 'Grid Panel Example' //titre de la grille

});

Le ColumnModel permet de définir les colonnes du tableau, pour chaque colonne on doit définir au minimum :

- Header : le texte d’en-tête de colonne

- dataIndex : permet de mapper la colonne avec les données provenant du store, ce champ correspond à l’attribut « name » de l’objet Record.

L’attribut sortable est optionnel et permet de mettre en place le tri pour la colonne en question.

Il ne reste plus maintenant qu’à afficher la grille et charger les données à partir du store :

//Afficher la grille
gr.render();
//Charger les données
store.load({});

Voici le résultat :

image

Conclusion :

Ce qu’on a fait ici c’est le tableau le plus basique qu’on peut faire avec le framework extjs, on peut bien évidemment l’enrichir avec la sélection multiple, la pagination en utilisant la bbar ou encore rajouter des fonctions de groupage par champ implémentées par le framework extjs.

Mais au delà de la grille qu’on a dessinée, on remarque encore et toujours le côté simple et intuitif de ce framework.

Partie Serveur (Services WCF) : serveur.zip

Partie Serveur (Services WCF) : serveur.zip

Partie Serveur (Services WCF) : serveur.zip

Extjs | Javascript | WCF
Monday, March 16, 2009 10:46:17 AM (Romance Standard Time, UTC+01:00) #    Comments [1]  | 

 

All content © 2012, Zied Nemili