| Summary: Some usefull examples |
| Author: RapotOR |
| Published: 17/01/2008 |
| Ext Version: v2.0 |
Languages: English Français
|
Contents |
( 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... :)
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
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
It's very usefull to select first data for combo & grid.
[[2 Solutions:]]
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%' });
You can use the same technic but the final line is :
MyGrid.getSelectionModel().selectRow(0);
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' });
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... ... });
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'); }, ...
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; }
singleselect... of course!
... sm: new Ext.grid.RowSelectionModel({singleSelect:true}), ...
... // 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' }) } ...
... // 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 } ...
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')); } } } });
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.
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...
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();
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); });
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... )
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); } });
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!'); } }); } } ...