jeudi 26 février 2009

Grille ExtJS et Zend Framework (2eme partie)

Dans cette partie nous allons construire et afficher notre grille, pour ce faite nous avons besoin de définir ces propriétés et sa source de données (DataStore dans le jargon ExtJS).

DataStore

Le DataStore est un tableaux de données qui peut être charger depuis n’importe quel source de données (XML, JSON...etc) ,pour que notre grille puisse afficher des données elle doit être impérativement attacher un DataStore, à un moment donnée si nous voulons changer le contenu de notre grille nous devrons changer celui du DataStore.

Pour commencer nous allons créer un nouveau fichier javascript grille.js dans le dossier js et nous lui ajouterons les fragments de  code qui suivent à la filé .

public/js/grille.js
var articlesDataStore;
var articlesCols;
var articlesListGrid;
var articlesListWindow;

Ext.onReady(function(){
   Ext.QuickTips.init();

Dans ce bout de code nous avons déclarer les variables dont nous aurons besoin plus bas, si vous avez remarqué le code ExtJS commence toujours par Ext.OnReady,cette méthode nous assure que tous les éléments ont été chargé avant de commencer a exécuté les scripts.

Nous allons maintenant définir notre DataStore.

public/js/grille.js
articlesDataStore = new Ext.data.Store({
       id: 'articlesDataStore',
    proxy: new Ext.data.HttpProxy({       // on vas utiliser une requette Http
                url: 'index/grille',  //url de l'action qui gère notre grille
                method: 'POST'       //on va utiliser la méthode poste pour notre requette
    
            }),
       baseParams:{gAction: "gListe"},  //on défini les paramètre à transmettre au l'action
         reader: new Ext.data.JsonReader({   
         root: 'results',
         totalProperty: 'total',
         id: 'id'
       },
    [ 
         {name: 'ref', type: 'string', mapping: 'ref'},
         {name: 'designation', type: 'string', mapping: 'designation'},
         {name: 'Qte', type: 'int', mapping: 'Qte'},
         {name: 'Prix', type: 'float', mapping: 'Prix'},
         {name: 'famille', type: 'string', mapping: 'famille'},
   {name: 'Libelle', type: 'string', mapping: 'Libelle'},
         {name: 'date_ent', type: 'date', mapping: 'date_ent'}
         
       ]),
       
       sortInfo:{field: 'ref', direction: "ASC"}
    
     });

Nous avons déterminés ci-dessus le proxy, BaseParams, reader et la  définition des champs du DataStore dont:

Proxy : définit la méthode, url et le type de requête à transmettre à notre Action dans notre cas (POST, ‘index/grille’ et Http).

BaseParams : c’est les données qui seront transmise via la requête, dans notre cas nous envoyons une variable gAction avec la valeur gListe.

reader : définit la structure et lit les valeurs des données de retour transmises par l’action grille.

Attention la casse est respecté dans les noms de colonnes, le mapping doit être tel qu'il est définit dans votre base de données et le champ name au dataIndex du ColumnModel.

ColumnModel

dans le ColumnModel nous allons définir l’apparence et le comportement de chaque colonne de la grille

public/js/grille.js
  articlesCols = new Ext.grid.ColumnModel([
  {
   header: 'Ref.',
   readOnly: true,
   dataIndex: 'ref', 
   width: 60,
   hidden: false
  },
  {
   header: 'Désignation',
   readOnly: true,
   dataIndex: 'designation', 
   width: 200,
   hidden: false
  },
  {
   header: 'Qte',
   readOnly: true,
   dataIndex: 'Qte', 
   width: 50,
   align:'right',
   hidden: false
  },
  {
   header: 'Prix',
   readOnly: true,
   dataIndex: 'Prix', 
   width: 80,
   hidden: false,
   renderer: Ext.util.Format.formatNumber.createDelegate(Ext.util.Format),
            align:'right',
  
  },
  {
   header: 'Familles',
   readOnly: true,
   dataIndex: 'famille',
   width: 50,
   hidden: true
  },
  {
   header: 'Familles',
   readOnly: true,
   dataIndex: 'Libelle',
   width: 150,
   hidden: false
  },
  {
   header: 'Date d\'entrée',
   readOnly: true,
   dataIndex: 'date_ent', 
   width: 80,
   hidden: false,
   renderer:Ext.util.Format.dateRenderer('d/m/Y')
  }
  ]);

Malheureusement ExtJS 2.0 n’inclut pas de base un moyen de formatage pour les monétaires ou pour le groupage des numériques par millier, alors les membres de la communauté ExtJS on développé une extension qui nous permettra de formater notre colonne Prix.

lien de téléchargement de l’extension.

Nous  devrons mettre cette extension dans notre dossier js et insérer le script dans le l’entête de notre layout

Comme nous avons terminé de définir le DataStore et le ColumnModel, nous somme enfin prêts à créer notre grille, dans notre exemple nous avons choisi de mettre celle-ci dans une fenêtre flottante mais ce n’est pas une nécessité, vous la placer dans n’importe quel conteneur.  

public/js/grille.js
 
      articlesListGrid =  new Ext.grid.EditorGridPanel({
          id: 'articlesListGrid',
       title:'liste des employe',
          store: articlesDataStore,     // Définition du lien avec le DataStroe
       cm: articlesCols,        // affectation des colonnes  
       enableColLock:false,
       selModel: new Ext.grid.RowSelectionModel({singleSelect:false})

       });
       
  articlesListWindow = new Ext.Window({  //nous mettons notre grille dans une fenêtre flottante
      id: 'articlesListWindow',
      title: 'list articles',
      closable:true,
      width:700,
      height:350,
      plain:true,
      layout: 'fit',
     items: articlesListGrid  
    });
  
  articlesDataStore.load();
 
  articlesListWindow.show();   // Display our window
  
 
});

Nous avons terminé la conception de notre grille mais tous de même nous ne pourrons pas encore l’afficher, nous devons d’abord effectuer quelques modifications sur l’action grille de notre contrôleur Index comme nous l’avons prédis dans la première partie.

Application/Controllers/IndexController.php
    switch ($gAction) {
     case "gListe" :
       $data = array();
       $rows =$article->lister();
            foreach ($rows as  $key=>$row)
                    {
                     $date =new Zend_Date($rows[$key]['date_ent'] ,Zend_Date::ISO_8601);
                     $rows[$key]['date_ent'] =$date->toString('MM/dd/yyyy');
                    
                     }
        $data['results'] = $rows;
                          $data['total'] = count($rows);
                          $resultat = Zend_Json :: encode($data);
      break;

  

Nous avons défini ici la traitement à effectuer lorsque en reçoit la requête POST quand gAction = gListe comme suit.

  1. Récupération de la liste des articles.
  2. Conversion des dates du format MySQL en format JavaScript  YYYY-MM-DD =>  mm/dd/yyyy.
  3. encodé le tous en JSON.

Dans cette exemple nous avons défini tous les traitements dans notre action ce qui n’est pas très judicieux, le mieux est de définir des fonctions dans notre model auxquelles nous ferons appel pour mieux respecter le concept MVC et de décharger notre action pour une meilleur clarté de notre code.

Nous rajoutons maintenant la touche finale en appelons le script grille.js dans notre vue Index.

Application/views/scripts/index.phtml
<script type="text/javascript" src="<?php echo $this->baseUrl();?>/public/Js/grille.js"></script>

Nous arrivons a la fin de cette partie qui consiste à afficher la grille mais ce n’est pas encore fini, dans la partie suivante nous allons lui rajouter un peut de punch en lui ajoutant les fonctionnalités d’édition,d’ajout et de suppression.

8 commentaires:

  1. Salut,
    Merci beaucoup pour ce tuto il est très instructif. C'est un bel exemple d'association entre zend et extjs.
    Malheureusement, quand je le teste ça ne marche pas: j'obtiens bien la grille mais sans aucune données à l'intérieure.
    En fait, quand je regarde le contenu du champ resultat de mes données JSON, il est vide.
    Donc le traitement dans le controller ne semble pas fonctionner. Finalement, j'ai trouvé d'où venait mon problème.
    Dans la méthode lister de la classe Article, on retourne $this->fetchAll ( $select );
    C'est donc un objet de type Zend_Db_Table_Rowset. Cet objet n'est pas directement exploitable par un foreach.
    Par conséquent, dans le controller, j'ai juste rajouter l'appel à la méthode toArray qui permet de convertir cet objet en tableau:
    j'ai donc remplacé $rows =$article->lister(); par
    $rows =$article->lister()->toArray();
    Et ça marche très bien.
    Merci encore pour ce tuto

    RépondreSupprimer
  2. vous avez bien vu, j'ai pas fais de mise à jours pour le premier ticket car j'ai changer mon model, j'ai transformé le résultat directement en tableau dans ma fonction lister().

    [code]
    class Articles extends Zend_Db_Table {
    protected $_name = 'articles';
    protected $_primary = array ('ref' );

    public function lister() {
    $select = $this->select ();
    $select->from ( 'articles', '*' )
    ->setIntegrityCheck ( false )
    ->join ( 'familles', 'familles.id=articles.famille', 'Libelle' );

    $rows = $this->fetchAll( $select )->toArray();



    return $rows;
    }

    }
    [/code]

    RépondreSupprimer
  3. download..!!! download download

    RépondreSupprimer
  4. Hello, cela ne fonctionne pas, j'ai bien la fenetre mais pas de données. Avez-vous une idée ?

    RépondreSupprimer
  5. En fait le nom des classes cité dans cet exemple n'est pas correct dans la nouvelle version de ZF.. j'ai changé et cela fonctionne maintenant

    RépondreSupprimer
  6. Savez-vous comment ne plus rendre la fenêtre flottante ? Merci d'avance

    RépondreSupprimer
  7. This blog was... how do I say it? Relevant!! Finally I've found something that helped me. Thank you!

    Feel free to surf to my web blog - web site

    RépondreSupprimer