Ext JS - Learning Center

Tutorial:Some Usefull examples

From Learn About the Ext JavaScript Library

Revision as of 15:26, 22 January 2008 by Rapotor (Talk | contribs)
(diff) ← Older revision | Current revision (diff) | Newer revision → (diff)
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

( First, sorry for my bad english )

I realized an application for me. At beginning with ExtJs, a lot of problem come at me and I would like to gather all of them in this tutorial to help any body who want begin. My search-time in forums was not negligible. Maybe yours will be smaller with this tutorial.

Finally, I would like to say that my knowledge of ExtJs isn't yet very good: then, sorry for any bullshits... I want help you... :)

Oriented Object Programation

I realized my first version without OOP but it was an error for a big application... I think. OOP is very more easy to use. http://extjs.com/learn/Manual:Basic_Application_Design

s.gif on internet? No no!!

It's in other tutorial but once more is better than less time in.

Add this in your code to use local s.gif:

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

Select first

It's very usefull to select first data for combo & grid.

Combo

[[2 Solutions:]]

First one:

Your store is already created & loaded in your OOP application. For small and very used stores, I load them at initializing of my class.

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); // FINAL LINE
     // MyCombo.setValue(MyCombo.store.collect('id', true)[0]); // this line isn't rapid
   }
 }
});

Second one: your store is must be loaded first. Use 'load' event on store.

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); // FINAL LINE
       // MyCombo.setValue(MyCombo.store.collect('id', true)[0]);  // this line isn't rapid
     }
   }
   reader: new Ext.data.JsonReader({
     root: 'data'  // root of data... comment it if necessary
   }, ['id','field1', 'field2'])
 }),                          
 valueField: 'id',
 editable: false,
 typeAhead: true,
 mode: 'local',
 triggerAction: 'all',
 emptyText:'Choose...',
 selectOnFocus:true,
 forceSelection : true,
 anchor:'95%'
});

Grid

You can use the same technic but the final line is :

MyGrid.getSelectionModel().selectRow(0);

Combo examples

Just a little code showing how display more than a field in your combo:

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'
});

Grid examples and tricks

Custom column display

A little example for customizing column display... Imagine anything because it's possible!

var cmLIST = new Ext.grid.ColumnModel([
{
  // add text at field
  header: "ID",
  dataIndex: 'id',
  sortable: true,
  renderer: function(v,params,record){
    return 'TOTO-'+v;
  },
  width: 30         
},{
  // add html...
  header: "Field 1",
  dataIndex: 'field1',
  sortable: true,
  renderer: function(v,params,record){
    return '<b>'+v+'</b>';
  },
  width: 50     
},{
  // use an other field with current field, add color..
  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
},{
  // display a date !
  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
},{
  // add a not existing field with others
  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,  // a store created before...
  cm: cmLIST,  // it's here...
  ...
});

Column display from a store

A lot of time, with databases, you get an id which is matching with a different store. The following code show how render a field matching with ID from grid's store.

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

Row display

In GridPanel, you can use 'getRowClass' function into 'view' property to change css value of the row.

...
  view: new Ext.grid.GridView({
     getRowClass: function(row, index) {
         var cls = '';
         var data = row.data;
 
         // here a test... customize yours!
         if ( data.field1 < 0  ) {
            cls = 'row-invalid'; // assign css class in some condition!
         }else{
            cls = '';
         }
 
         return cls;
     }
  }),
...
// my css class...
.row-invalid { 
    background-color: red !important;
}

Select only one row

singleselect... of course!

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

EditorGrid examples and tricks

Date column

...
// in the 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'
  })
} 
...

Combo editor column

...
// in the ColumnModel
{
  header: "Suppliers",
  dataIndex: 'supplierid',
  sortable: true,     
  width: 80,
  renderer: function(v, params, record){ 
   return storeSuppliers.getAt(storeSuppliers.find('id',v)).get('name');      
  },  
  editor: new Ext.form.ComboBox({
    store: storeSuppliers,
    triggerAction: 'all',
    emptyText:'',
    selectOnFocus: true,
    valueField: 'id',
    displayField: 'name'
  }),
  width: 200 
} 
...

Dynamical editor

Maybe you must use a different editor depending of data. For this example, we will use sometimes a textfield, sometimes a combobox as editor.

var storeField = new Ext.data.Store({
   url: 'getdata.php',
   reader: new Ext.data.JsonReader({
      root: 'enreg'
   }, ['id','field1', 'field2'])
});
 
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
});
 
// editor object from combo        
var objEditorCombo = new Ext.grid.GridEditor(editorCombo);
 
var editorText = new Ext.form.TextField({ allowBlank: false });    
 
// editor object from 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  // place by default an editor !
}
//.... 
]); 
 
var myGrid = new Ext.grid.EditorGridPanel({
  store: myStore,
  // ... any properties
  cm: cmLIST,  // my column model
  listeners:{
      celldblclick: function(grid, rowIndex, columnIndex, e){
 
          // only for 'field1' field...
          if (grid.getColumnModel().getDataIndex(columnIndex) == "field1"){
             // an example of test...
             if (grid.store.getAt(rowIndex).get('field2') == 0){
                 // set textfield editor in this case
                 grid.getColumnModel().setEditor(columnIndex,objEditorText);
             }else{
                 // set combo editor
                 grid.getColumnModel().setEditor(columnIndex,objEditorCombo);
             }
          }
 
      },
      afteredit: function(e){
 
        if (e.field == 'field1' && e.record.get('field2') == 0){
           // if editor is my combo for the field, after edit, maybe you want assign another field from the combo's store to the grid's store. 
           e.record.set('field2',storeField.getAt(storeField.find('id',e.value)).get('field2'));           
        }
 
      }  
  }
});

Avoid some leaks

Many topics speak about leaks. What's that? With some component use, some DIV are not destroyed and the memory is really increasing... I have seen that with msg, modal windows, grid at this moment.

Ext.msg

Not really a problem because at each showing, shadow (...) DIV aren't created at each time; there are used again at each 'show'. Then, it's not necessary to destroy it...

Modal window

Argh! REALLY BAD... I have created a extend to destroy automatically shadow, mask...

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);}
 
    }
  }
 
});
 
// and use it :
 
var modalWin = new Ext.ModalWindow({
 
  id: 'modalWin',
 
  title: 'Intranet Logon.',
 
  width: 360,
 
  buttons: [
  {
    text: 'Quit',
    handler: function(){
       modalWin.destroy();
    }
  }]
 
});        
 
modalWin.show();

Clear panel

In this case, i had some grids into a panel and some DIV were not always destroyed.

// example of forgotten div for a grid (in my application)
<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"/>

The better way for me was :

myPanel.items.each(function(item, index, len){
   item.purgeListeners();
   myPanel.remove(item,true);
 });

Form with grid

As some people on the forum, I wanted to put a grid into a formpanel... but of course, it wasn't so easy ... :D Here, it's my method. Maybe there are some others. ( An extend of a formpanel with grid will be better... )

Loading data

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);
 
       // set data into grid from a grid1
       var myGrid = Ext.getCmp('myGrid');
       myGrid.store.loadData(myResponse.grid1);
 
     }
 });

Saving data

var myForm = new Ext.form.FormPanel({
  ...
  items: [
  {
    xtype: 'textfield',
    name: 'field1',
    fieldLabel: 'Field 1'
  },{
    xtype: 'textfield',
    name: 'field2',
    fieldLabel: 'Field 2'
  },{
    xtype: 'grid',
    // ... some properties here
  }
  ]
  bbar: [     
  {
     xtype: 'button', // it's the same as use "new Ext.Button()" (see doc)
     text: 'Save' ,
     iconCls: 'save', 
     handler : function() {
 
       var storeValue=[];
       var myGrid = Ext.getCmp('myGrid');
       var allRecords = myGrid.store.getRange(0);
 
       // set data into storevalue
       for (i=0;i < allRecords.length;i++)
       {
         storeValue[i] = allRecords[i].data;
       }
 
       // get data from form
       var dataForm = generalInfos.getForm().getValues();
 
       Ext.Ajax.request({
 
         url: 'submitdata.php',
 
         params: {
            param1: 'toto',
            param2: 'titi',
            field1: dataForm.field1,
            field2: dataForm.field2,
            grid1: Ext.encode(storeValue)  // I putted it in json format...
         },
 
         callback: function(options,success,response){
 
            alert('SUBMIT!');
 
         }
 
       }); 
     }
  }
  ...