Ext JS - Learning Center

Tutorial:Quelques exemples utiles

From Learn About the Ext JavaScript Library

Jump to: navigation, search
Summary: Some usefull examples
Author: RapotOR
Published: 17/01/2008
Ext Version: v2.0
Languages: en.png English fr.png Français

Contents

Introduction

J'ai réalisé une application personnelle. A mes débuts avec ExtJs, pas mal de problèmes sont venu bloquer ma progression et j'ai voulu les rassembler dans ce tutoriel pour aider les personnes qui débutent. Mes recherches dans la doc et les forums a été assez importante. J'espère que la votre sera beaucoup plus petite grâce à ce tutoriel.

Enfin, je voudrais préciser que ma connaissance de ExtJs n'est pas encore parfaite; il y a donc certainement des améliorations possibles au code. Donc, désolé pour d'éventuelles conneries... Je veux juste vous aider :)

Programmation Orientée Object

J'avais réalisé ma première version de mon application sans PPO mais c'était une erreur pour une grosse application... Je pense. PPO est beaucoup plus simple d'utilisation. Voici une adresse : http://extjs.com/learn/Manual:Basic_Application_Design

s.gif sur internet?? Non!!!

C'est déjà présent dans d'autres tutoriels mais une fois de plus vaut mieux qu'une fois de moins.

Ajoutez cette ligne pour que ExtJs utilise l'image locale:

Ext.BLANK_IMAGE_URL = 'ext/resources/images/default/s.gif';  // 2.0

Selection de la première ligne

C'est toujours utile de pouvoir selectionner la première ligne d'un combo ou d'une grid.

Les Combo

[[2 Solutions:]]

Première:

Votre 'store' est déjà créé et charger dans votre application (orientée object). Effectivement, j'ai personnellement changé mes stores petits et souvent utilisés dans ma classe.

var MyCombo = new Ext.form.ComboBox({
 displayField:'field1',
 store: store1,                          
 valueField: 'id',
 editable: false,
 typeAhead: true,
 mode: 'local',
 triggerAction: 'all',
 emptyText:'Choose...',
 selectOnFocus:true,
 forceSelection : true,
 anchor:'95%',
 listeners: {
   beforerender: function(combo){
     MyCombo.setValue(MyCombo.store.getAt(0).data.id); // Ligne finale
     // MyCombo.setValue(MyCombo.store.collect('id', true)[0]); //pas assez rapide
   }
 }
});

La ligne finale est la ligne correspondant à la selection de la première ligne. Le champ 'id' correspond au champ 'valueField'.

Deuxième: La deuxième solution envisage le cas ou il faut également créer le store avec le combo.

var MyCombo = new Ext.form.ComboBox({
 displayField:'field1',
 store: new Ext.data.store({
   url: 'getdata.php',
   autoLoad: true,
   listeners: {
     load: function(){
       MyCombo.setValue(MyCombo.store.getAt(0).data.id); // Ligne finale
       // MyCombo.setValue(MyCombo.store.collect('id', true)[0]);  // pas assez rapide
     }
   }
   reader: new Ext.data.JsonReader({
     root: 'data'  // le champ 'root' des données; à enlever si nécessaire
   }, ['id','field1', 'field2'])
 }),                          
 valueField: 'id',
 editable: false,
 typeAhead: true,
 mode: 'local',
 triggerAction: 'all',
 emptyText:'Choose...',
 selectOnFocus:true,
 forceSelection : true,
 anchor:'95%'
});

Les Grid

Pour les grids, c'est le meme système à part qu'on utilise comme ligne finale celle ci :

MyGrid.getSelectionModel().selectRow(0);

Examples avec Combo

Alors ici, c'est une petit code pour montre plusieurs champs dans le combo. On utilise un template : tpl.

var myCombo = new Ext.form.ComboBox({
 // use tpl !!!
 tpl: '<tpl for="."><div class="x-combo-list-item">{id} > {field1}</div></tpl>',
 valueField: 'id',
 store: myStore,
 allowBlank: true,
 typeAhead: true,
 mode: 'local',
 triggerAction: 'all'
});

Examples et astuces pour Grid

Différents affichages de colonnes

Voici quelques exemples d'affichage de différentes données pour vous donner des idées. Vous pouvez envisage tout et n'importe quoi.

// donc on crée un objet 'ColumnModel'
var cmLIST = new Ext.grid.ColumnModel([
{
  // ajouter un peu de text à la value du champ
  header: "ID",
  dataIndex: 'id',
  sortable: true,
  renderer: function(v,params,record){
    return 'TOTO-'+v;
  },
  width: 30         
},{
  // On peut meme ajouter de l'HTML
  header: "Field 1",
  dataIndex: 'field1',
  sortable: true,
  renderer: function(v,params,record){
    return '<b>'+v+'</b>';
  },
  width: 50     
},{
  // Utiliser un autre champ dans celui en cours; ajouter de la couleur...
  // par exemple, ici, j'utilise le field3 pour afficher le field2.
  header: "Field 2",
  dataIndex: 'field2',
  sortable: true,
  renderer: function(v,params,record){
    if (record.data.field3 == 1){
      // imagine that 'field2' is an other field in store
      return v+':<font color="#00FF00">'+record.data.field3+'</font>';
    }else{
      return v+':<font color="#FF0000">'+record.data.field3+'</font>';
    }
  },
  width: 50
},{
  // afficher une date. :)
  // perso j'utilise tjs le temps unix... un petit format et hop!
  header: "Date",
  dataIndex: 'fielddate',
  sortable: true,     
  renderer: function(v,params,record){
   return Ext.util.Format.date(v,'d-m-Y');  // change the mask if you want..
  },    
  width: 50
},{
  // On peut meme ajouter un champ imaginaire calculé à partir d'existants
  header: "Cost",
  width: 60,
  renderer: function(v, params, record){
    return (record.data.pricebyunit * record.data.quantity);
  },
  sortable: true
}
]);
 
var myGrid= new Ext.grid.GridPanel({
  id: 'myGrid',
  anchor: '100% 100%',
  store: myStore,  // ici un store déjà créé avant. avec les différents champs
  cm: cmLIST,  // et ici on définit l'utilisation de notre ColumnModel
  ...
});

Colonne à partir d'un store

Dans la plus part des cas, avec la configuration des bases de données, on utilise des ID pour faire un lien avec une autre table. alors évidement, on récupère des numéros dans certains champs et pas une valeur texte ou autre. Pour ca, la ligne suivante permet la récupération dans un autre store que celui de la grid du texte correspondant à un ID.

...
  // Dans un champ du ColumnModel
  renderer: function(v, params, record){ 
     return store2.getAt(stores2.find('id',v)).get('field1');      
  },  
...

Affichage d'une ligne

Dans le GridPanel, vous pouvez utiliser la fonction 'getRowClass' dans la propriété 'view' pour changer la css de la ligne.

...
  view: new Ext.grid.GridView({
     getRowClass: function(row, index) {
         var cls = '';
         var data = row.data;
 
         // ici un petit test pour changer ou pas la css... changez par le votre!
         if ( data.field1 < 0  ) {
            cls = 'row-invalid'; // on assigne le nom d'une classe css!
         }else{
            cls = '';
         }
 
         return cls; // on retource la valeur...
     }
  }),
...
// ici ma classe css qui rendra rouge la ligne si on l'utilise... bien sûr!
.row-invalid { 
    background-color: red !important;
}

Selectionner une seule ligne

La propriété singleselect... bien sur!

...
  sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
...

Examples et astuces avec EditorGrid

Colonne Date

Ici on doit pouvoir afficher la date correctement et en même temps l'éditer !! wow!!

...
// dans le ColumnModel
{
  header: "Date",
  dataIndex: 'datefield',
  sortable: true,     
  renderer: Ext.util.Format.dateRenderer('d-m-Y'), 
  width: 80,
  editor: new Ext.form.DateField({
    format: 'd-m-Y'
  })
} 
...

Colonne avec combo

...
// dans le ColumnModel
{
  header: "Suppliers",
  dataIndex: 'supplierid',
  sortable: true,     
  width: 80,
  renderer: function(v, params, record){ 
   // ici on affiche la value à partir du store comme déjà montré dans la section grid
   return storeSuppliers.getAt(storeSuppliers.find('id',v)).get('name');      
  }, 
  // et on crée notre combo qui va chercher dans le meme store
  // ainsi la valeur du champ est tjs l'ID et pas le texte! 
  editor: new Ext.form.ComboBox({
    store: storeSuppliers,
    triggerAction: 'all',
    emptyText:'',
    selectOnFocus: true,
    valueField: 'id',
    displayField: 'name'
  }),
  width: 200 
} 
...

Editeur dynamique

Peut être que vous devriez avoir besoin de changer l'éditeur en fonction des données. Pour cet exemple, je vais utiliser parfois un textfield ou parfois un combo!

// a store
var storeField = new Ext.data.Store({
   url: 'getdata.php',
   reader: new Ext.data.JsonReader({
      root: 'enreg'
   }, ['id','field1', 'field2'])
});
 
// un combo         
var editorCombo = new Ext.form.ComboBox({
   valueField: 'id',
   displayField: 'field1',
   store: storeField,
   allowBlank: true,
   typeAhead: true,
   mode: 'local',
   triggerAction: 'all',
   emptyText:'Choose...',
   selectOnFocus: true,
   forceSelection : true,
   editable: true
});
 
// ici on crée l'éditeur en fonction du combo        
var objEditorCombo = new Ext.grid.GridEditor(editorCombo);
 
// un textfield
var editorText = new Ext.form.TextField({ allowBlank: false });    
 
// ici on crée l'éditeur en fonction du textfield
var objEditorText = new Ext.grid.GridEditor(editorText);
 
var cmLIST = new Ext.grid.ColumnModel([
//...
{
  header: "Field 1",
  dataIndex: 'field1',
  sortable: true,   
  width: 400,  
  editor: objEditorCombo  // on assigne un des 2 éditeurs.
}
//.... 
]); 
 
var myGrid = new Ext.grid.EditorGridPanel({
  store: myStore,
  // ... ici, n'importe quelle propriétés..
  cm: cmLIST,  // my column model
  listeners:{
      // au moment du double click on va changer l'éditeur
      celldblclick: function(grid, rowIndex, columnIndex, e){
 
          // mais seulement pour le champ 'field1'...
          // faudrait pas le changer pour un autre ;)
          if (grid.getColumnModel().getDataIndex(columnIndex) == "field1"){
             // ici un test exemple... à changer par le votre
             if (grid.store.getAt(rowIndex).get('field2') == 0){
                 // on assigne dans ce cas le textfield
                 grid.getColumnModel().setEditor(columnIndex,objEditorText);
             }else{
                 // et dans l'autre le combo
                 grid.getColumnModel().setEditor(columnIndex,objEditorCombo);
             }
          }
 
      },
      afteredit: function(e){
        // après l'édition, dans le cas ou l'éditeur était le combo,
        // il se pourrait qu'il faille changer en même temps d'autres colonnes
        // qui sont liées.        
        if (e.field == 'field1' && e.record.get('field2') == 0){
e.record.set('field2',storeField.getAt(storeField.find('id',e.value)).get('field2'));           
        }
 
      }  
  }
});

Eviter des pertes de mémoire

Il y a pas mal de topics qui parlent de pertes de mémoires. Qu'est ce que c'est? Avec l'utilisation de certains composants, certaines DIV ne sont pas détruites avec l'utilisation de l'application et la mémoire augmente sans cesse... J'ai remarqué cela avec msg, modal windows, grid pour l'instant. Vous vérifier cela, utilisez l'extension FIREBUG sous FIREFOX.

Ext.msg

Ce n'est en fait pas vraiment un problème. A chaque fois qu'une fenêtre apparaît, les 'shadow' (masque, ombres sous les fenêtres etc...) DIV ne sont pas créées à chaque fois; elles sont réutilisées à nouveau à chaque fenêtre ('show'). Donc ce n'est pas nécessaire de les supprimer.

Modal window

Argh! Pas très bon! C'est la fenêtre avec l'option d'un masque qui cache l'application en arrière. J'ai créé une petite extend de Ext.Window avec un listener qui supprimer les mask, shadow correspondants

Ext.ModalWindow = Ext.extend(Ext.Window, {
 
  initComponent : function(){
    Ext.Window.superclass.initComponent.call(this);
  },
 
  modal: true,
 
  closable: true,
 
  modal: true,
 
  shadow: false,
 
  minimizable: false,
 
  draggable: false,
 
  resizable: false,
 
  width: 500,
 
  height: 'auto',
 
  layout: 'anchor',
 
  plain: true, 
 
  listeners: {
 
    beforedestroy: function(w){
 
      if (w.mask){Ext.destroy(w.mask);}
      if (w.proxy){Ext.destroy(w.proxy);}
      if (w.plain){Ext.destroy(w.plain);}
 
    }
  }
 
});
 
// et son utilisation :
 
var modalWin = new Ext.ModalWindow({
 
  id: 'modalWin',
 
  title: 'Intranet Logon.',
 
  width: 360,
 
  buttons: [
  {
    text: 'Quit',
    handler: function(){
       modalWin.destroy();
    }
  }]
 
});        
 
modalWin.show();

Vider un panel

Dans ce cas, j'avais quelques grids dans un panel et certaines DIV n'était pas supprimées. Du coup, à chaque fois, j'avais des DIV qui s'amoncelait... et la mémoire qui augmentait...

<div id="ext-gen728" class="x-dd-drag-proxy x-dd-drop-nodrop x-grid3-col-dd" style="position: absolute; z-index: 15000; visibility: hidden; left: -10000px; top: -10000px;">
<div class="x-dd-drop-icon"/>
<div id="ext-gen730" class="x-dd-drag-ghost"/>
</div>
<div id="ext-gen733" class="col-move-top"/>
<div id="ext-gen734" class="col-move-bottom"/>

La meilleure solution pour moi était :

myPanel.items.each(function(item, index, len){
   item.purgeListeners();
   myPanel.remove(item,true); 
   // le 'true' , cest pour l'option destroy.
   // à noter que le '.destroy', ca marchait pas des masses pour éviter les DIV restantes.
 });

Form avec grid

Comme pas mal de personnes sur le forum, j'ai voulu mettre une grid dans un formpanel... mais evidement, ce ne fut pas si facile au moment du submit ... :D Ici, c'est ma méthode. Peut être il y en a d'autres. ( Une extend du formpanel avec grid serait peut être mieux... )

Changement des données

Ext.Ajax.request({
    url: 'getdata.php?type=da&idv='+PR_ID,
    callback: function(options,success,response){
 
       var myResponse = Ext.util.JSON.decode(response.responseText);
 
       myForm.form.setValues(myResponse);
 
       // mettre les données dans la grid à partir du champ grid1
       var myGrid = Ext.getCmp('myGrid');
       myGrid.store.loadData(myResponse.grid1);
 
     }
 });

Savegarde des données

var myForm = new Ext.form.FormPanel({
  ...
  items: [
  {
    xtype: 'textfield',
    name: 'field1',
    fieldLabel: 'Field 1'
  },{
    xtype: 'textfield',
    name: 'field2',
    fieldLabel: 'Field 2'
  },{
    xtype: 'grid',
    // ... d'autres propriétés ici
  }
  ]
  bbar: [     
  {
     xtype: 'button', // c'est le même que d'utiliser "new Ext.Button()" (voir doc)
     text: 'Save' ,
     iconCls: 'save', 
     handler : function() {
 
       var storeValue=[];
       var myGrid = Ext.getCmp('myGrid');
       var allRecords = myGrid.store.getRange(0);
 
       // je mets les données dans une variable storeValue
       for (i=0;i < allRecords.length;i++)
       {
         storeValue[i] = allRecords[i].data;
       }
 
       // je récup les données de la form
       var dataForm = generalInfos.getForm().getValues();
 
       // j'envoi la requete ajax avec les données complètes.
       Ext.Ajax.request({
 
         url: 'submitdata.php',
 
         // je paramètre la requête                      
         params: {
            param1: 'toto',
            param2: 'titi',
            field1: dataForm.field1,
            field2: dataForm.field2,
            grid1: Ext.encode(storeValue)  // Données de la grid au format JSON...
         },
 
         callback: function(options,success,response){
 
            alert('SUBMIT!');
 
         }
 
       }); 
     }
  }
  ...
  • This page was last modified 15:26, 22 January 2008.
  • This page has been accessed 7,979 times.