mercredi 18 mars 2009

IDE pour ExtJS

ExtJS est sans doute l’un des meilleurs Framework AJAX du moments mais développer avec n’est pas partie de plaisir pour les novices et même pour les plus expérimenté vue les nombreuses propriétés, méthodes et événement dont il faut se souvenir et le pire est que la casse et respecté. 

Mais soyez sans crainte ce n’est pas ce qui va vous empêcher de vous y mettre, les IDE ou EDI sont la pour nous décharger de cette tâche, après mes recherche j’ai repéré deux IDE intéressant dont Aptana et Spket

Aptana

logo aptana

Aptana est un IDE complet pour le développement web basé sur eclipse il  offre des support et plugins  pour plusieurs langages et des plugins plusieurs bibliothèques AJAX dont ExtJS,l’installation du plugins est d’une simplicité inouïe, vous n’avez qu’a cocher l’option ExtJS dans le Help Install Aptana Features... .

   aptana log

l’inconvénient avec le plugins d’Aptana est qu’il ne s’install pas sur d’autres plateformes eclipse tel que PDT ou Zend Studio.

Spket.

ide_m

Spket est un puissant EDI JavaScript gratuit pour un usage non commercial ,il peut être installé tout seul (standalone) ou comme plugins pour tous EDI basé sur eclipse d’ou son avantage, il nous offre l’achèvement de code et la coloration syntaxique.

un tutoriel est disponible sur le site officiel nous montrons comment installé l’extension ExtJS,je vais publier prochainement un tutoriel complet sur l’installation du plugins sur PDT eclipse ou Zend Studio.  

lundi 9 mars 2009

Grille ExtJS et Zend Framework (3eme partie)

Dans cette partie nous allons en premier lieux ajouter la fonctionnalité d’édition directement sur notre grille pour ce faite ne devons revenir sur notre ColumnModel pour redéfinir les colonnes en leur rajoutant les éditeurs (editor) adéquat pour chacune d’elle, mais avant tous nous allons déclarer un deuxièmes DataStore pour récupérer la listes des familles.
notre ColumnModel deviendra comme suit:
public/js/grille.js
famillesDataStore = new Ext.data.Store({
    id : 'famillesDataStore',
    proxy : new Ext.data.HttpProxy({
       url : 'index/grille',
       method : 'POST'

      }),
    baseParams : {
     gAction : "gListeFamille"
    },
    reader : new Ext.data.JsonReader({
       root : 'results',
       id : 'id'
      }, [{
         name : 'id',
         type : 'int',
         mapping : 'id'
        }, {
         name : 'Libelle',
         type : 'string',
         mapping : 'Libelle'
        }

      ]),

    sortInfo : {
     field : 'Libelle',
     direction : "ASC"
    }

   });


articlesCols = new Ext.grid.ColumnModel([{
    header : 'Ref.',
    allowBlank : false,
    readOnly : true,
    dataIndex : 'ref',
    width : 60,
    hidden : false,
    editor : new Ext.form.TextField({ // rules about editing
     allowBlank : false,
     maxLength : 9,
     maskRe : /([a-zA-Z0-9\s-]+)$/
    })
   }, {
    header : 'Désignation',

    dataIndex : 'designation',
    width : 200,
    hidden : false,
    editor : new Ext.form.TextField({ // rules about editing
     allowBlank : false,
     maxLength : 20,
     maskRe : /([a-zA-Z0-9\s]+)$/
    })
    // alphanumeric + spaces allowed

  } , {
    header : 'Qte',
    readOnly : true,
    dataIndex : 'Qte',
    width : 50,
    align : 'right',
    hidden : false,
    editor : new Ext.form.NumberField({
       allowBlank : false,
       decimalSeparator : ',',
       allowDecimals : true,
       allowNegative : false,
       blankText : '0',
       maxLength : 4
      })

   }, {
    header : 'Prix',
    readOnly : true,
    dataIndex : 'Prix',
    width : 80,
    hidden : false,
    renderer : Ext.util.Format.formatNumber
      .createDelegate(Ext.util.Format),
    align : 'right',
    editor : new Ext.form.NumberField({
       allowBlank : false,
       decimalSeparator : ',',
       allowDecimals : true,
       allowNegative : false,
       blankText : '0',
       maxLength : 11
      })

   }, {
    header : 'Id Famille',
    readOnly : true,
    dataIndex : 'famille',
    width : 50,
    align : 'right',
    hidden : true,
    editor : new Ext.form.NumberField({
       allowBlank : false,
       allowDecimals : false,
       blankText : '0',
       maxLength : 4
      })

   }, {
    header : 'Familles',
    dataIndex : 'LibFamille',
    width : 150,
    editor : new Ext.form.ComboBox({
       store : famillesDataStore,
       typeAhead : true,
       triggerAction : 'all',
       mode : 'remote',
       displayField : 'Libelle',
       listeners : {
        select : {
         fn : function(e, rec) {
          var sm = articlesListGrid
            .getSelectionModel()
            .getSelected();
          sm.set('famille', rec.id);
         }
        }
       },

       listClass : 'x-combo-list-small'// ,

      })
   }, {
    header : 'Date d\'entrée',
    readOnly : true,
    dataIndex : 'date_ent',
    width : 80,
    hidden : false,
    renderer : Ext.util.Format.dateRenderer('d/m/Y'),
    editor : new Ext.form.DateField({
       format : 'd/m/Y'

      })

   }]);

 articlesListGrid = new Ext.grid.EditorGridPanel({
  id : 'articlesListGrid',
  title : 'liste des employe',
  store : articlesDataStore,
  width : 700,
  height : 350,
  cm : articlesCols,
  frame : true,
  clicksToEdit : 1,

  enableColLock : false,

  selModel : new Ext.grid.RowSelectionModel({
     singleSelect : true
    }),
  tbar : [{
     text : 'Ajouter',
     handler : function() {
      articleAction = 'gAjouter';
      var p = new article({
         ref : '',
         designation : '',
         Qte : '0',
         Prix : '0',
         date_ent : (new Date()).clearTime(),
         famille : '0'

        });

      articlesListGrid.stopEditing();
      articlesCols.setEditable(0, true);
      articlesDataStore.insert(0, p);
      articlesListGrid.startEditing(0, 0);
     }
    }]

   
  });
Nous allons définir ici la modification et l'ajout dans une même fonction, ce qui va compliquer un peut les choses mais va nous économisé énormément de code.
Pour pouvoir modifier, c’est simple, un double ou un simple click  (tous dépendra de la propriété clicksToEdit) sur la ligne souhaité et elle passe en mode édition mais pour l’ajout nous aurons besoin d’ajouter un bouton ajouter à notre grille.
Les grille ExtJS nous offre la possibilité de lui ajouter une barre d’outil qui va accueillir tous les boutons dont nous aurons besoin, vous allez voir c’est très simple, mais avant tous nous aurons besoin de déclarer une variable articleAction et une class record qui aurons pour rôle : .
articleAction permet à notre fonction d’enregistrement de déterminer si il s'agit d’un ajout ou d’une modification par défaut la variable et initialisé à “Modifier” et lorsque nous cliquons sur le bouton ajout nous la mettons a jours à “Ajout”.
le record article nous permet d’initialiser le nouvel enregistrement à insérer.
public/js/grille.js
// déclaration et initialisation articleAction.
 var articleAction = 'Modifier';
// déclaration de la classs record.
var article = Ext.data.Record.create([
   // the "name" below matches the tag name to read, except "availDate"
   // which is mapped to the tag "availability"
   {
  name : 'ref',
  type : 'string'
 }, {
  name : 'designation',
  type : 'string'
 }, {
  name : 'Qte',
  type : 'int'
 }, {
  name : 'Prix',
  type : 'float'
 }, {
  name : 'LibFamille',
  type : 'date',
  dateFormat : 'd/m/Y'
 }, {
  name : 'date_ent',
  type : 'date'
 }]);

 ....
 ....

selModel : new Ext.grid.RowSelectionModel({
     singleSelect : false
    }),
  tbar : [{
     text : 'Ajouter',
     iconCls:'ajout'
     handler : function() {
      articleAction = 'gAjouter';
      var p = new article({
         ref : '',
         designation : '',
         Qte : '0',
         Prix : '0',
         date_ent : (new Date()).clearTime(),
         famille : '0'

        });

      articlesListGrid.stopEditing();
      articlesCols.setEditable(0, true);
      articlesDataStore.insert(0, p);
      articlesListGrid.startEditing(0, 0);
     }
    }]

   
  });
Dans l’événement click du bouton (handler ) nous avons initialisé la variable articleAction et le record article.
Nous allons maintenant écrire notre fonction EnregistrerArticle qui va se charger de transmettre au serveur les données et l’action a entreprendre (ajout ou modification).
public/js/grille.js
function EnregistrerArticle(e) {

  Ext.Ajax.request({
   waitMsg : 'Enregistrement en cours...',
   url : 'index/grille',
   params : {
    gAction : articleAction,
    ref : e.record.data.ref,
    designation : e.record.data.designation,
    Qte : e.record.data.Qte,
    Prix : e.record.data.Prix,
    famille : e.record.data.famille, 
    date_ent : e.record.data.date_ent.format('Y-m-d')

   },
   success : function(response) {
    var result = eval(response.responseText);
    switch (result) {
     case 1 :
      articlesDataStore.commitChanges(); 
      articlesDataStore.reload();
      articleAction = 'Modifier';
      // reload our datastore.
      break;
      case 2 :
        Ext.MessageBox.alert('un article du même code exist déja !');
      break;
     default :
      Ext.MessageBox.alert('les données ne sont pas enregistré...');
      break;
    }
   },
   failure : function(response) {
    var result = response.responseText;
    Ext.MessageBox.alert('Erreur',result);
   }
  });
 }
  articlesListGrid.on('afteredit', EnregistrerArticle);
 
Dans la dernière ligne du code ci-dessus nous affectons à notre fonction a l’événement 'afteredit' qui se produit juste après qu'une cellule de notre grille est modifié notre fonction d’enregistrement.
nous avez terminé les modification sur notre fichier grille.js, maintenant nous allons repassé a notre contrôleur afin qu’il puisse répondre aux requête d’édition et d’ajout. 
Application/controllers/index.php
case "gListeFamille" :
      $famille = new familles();
         $resultat = $famille->fetchAll()->toArray(); 
        
      break;
case "gAjouter" :
      $article = new Articles ();
      $id = $formData['ref'];
      $row = ($article->find($id));
      if (empty($row['ref']))
      {
      unset($formData['gAction']);
        $article->insert($formData);
       $resultat = 1; 
      }
      else 
      {$resultat = 2;} // un Article du meme code exist déja
      // $resultat = .....     
      break;
      
     case "gModifier" :
                        
      $article = new Articles ();
      $id = $formData['ref'];
      $row = ($article->find($id));
      
      unset($formData['ref']);
      unset($formData['gAction']);
      $where = $article->getAdapter()->quoteInto('ref = ?', $id);
      $article->update($formData,$where);
      $resultat = 2;
     
      break;
 
Nous pouvons dès a présent testé notre code, vous pouvez constaté qu’il est belle et bien possible de modifier et d’ajouter des enregistrement.
Nous arrivons a la fin de cette partie qui est un peut complexe,si nous avons déclarer notre clé primaire auto-incrémenté les chose serais plus simple.
Dans la prochaine et dernière partie nous verrons comment ajouter à notre grille une barre de pagination et recherche rapide,si vous avez des problèmes faire fonctionner votre grille ou des commentaires je serai ravi d’y réponde.