1. Grid is empty
2. Grid Doesn’t show images correctly
3. Sorting issues
4. Grids inside Tab Panels
6. Combining Fields into One Column
7. How to modify appearance, behavior of specific rows or columns?
8. How to add click handlers to specific Grid cells?
9. Why is Store Empty even after calling load() on my Store
10. How to make grid resize with the window?
11. How to Update a cell (actually the store)?
12. How to reload a Grid from a different URL?
13. XML Issues
14. Grid still shows records even when it should be empty
15. How to debug what is going into Json Reader?
16. How to drag/drop/reorder rows?
17. Horizontal scrolling issues
18. Mixing fixed width and variable width columns
19. How to hide a column?
20. How to wrap contents within a cell of a fixed width grid column?
21. How to add a column with tools for each record?
22. How to center elements in a toolbar?
23. How to delete all selected rows?
24. Problems with paging or total record count
25. Get a record from the grid by row index
26. Load data to a grid from two diferent server calls/stores
27. "Auto size" columns to the largest element in them
28. Disable editing of particular rows
29. What is difference between contentEl, applyTo and renderTo?
30. Dirty Record / Red Flag display (modifying, etc.)
31. Editor Grid - ComboBox displays "<div class="x-grid-col-1 x-grid-cell-inner">[/

1. Grid is empty / Populating the grid problems:

• Grid doesn’t show data
• Grid is empty
• Grid didn’t render
• Grid not listening to store

Likely problems to check:

1. Did you define the grid height using one of the following? (height, autoHeight, or within a container with layout:‘fit’)
Code:
grid = new Ext.grid.EditorGridPanel({
//other configs...

//Don't forget to specify the height!
//Three options: (1) specify height explicitly, (2) enable autoHeight, (3) put grid inside a container with layout:'fit'
autoHeight:true //autoHeight resizes the height to show all records
//-or-
height:350
3. Did you render the grid? Render a grid using one of the following:
• use 'renderTo' or 'el' in the grid config to render automatically or
• defer rendering and explicitly render the grid using grid.render()
4. Does the element you rendered to exist?
5. If using JSON, is the JSON properly formed (paste the JSON response into the checker at http://www.jslint.com/ to verify)
6. Do not use periods in field names for JSON ("my.success"="ext will not decode")
7. Does the reader correctly specify the correct root for the JSON being used?
• Check the sample response packet from a JSONReader. You will want to set a root option (rows in example below) and then wrap your array in a JSON response. Something like:
Code:
{ 'results': 2, 'rows': [{"CodigoProduto":"3009","TipoProduto":"FERT","DescricaoProduto":"7 UP  Reg. 12 GR 1,50 PET",
"ProdutoPesoLiquido":"18.760","ProdutoPesoUM":"KG","ProdutoVolume":"18.000","ProdutoVolumeUM":"L",
"ProdutoUM_PAL":"36","Eliminar":""}]
}

Try to track down problems using firebug:

1. Were there any errors reported by firebug?
2. Was a request sent out (Check CONSOLE for requests that were POSTED).
3. Was a response received for the request?
If so, did you post it into http://www.jslint.com/ to verify it’s in proper form?
Is the response what you expected, shows total number of records, the root has an array, etc.?

Add listeners to see if the store loaded or if there were exceptions. See next post for listeners to add.
A few of the key listeners to watch for:

2. Grid Doesn’t show images correctly (checkboxes, etc.)

1. Are CSS files attached correctly? (Check Firebug, XHR for any red links)
2. The css references may be incorrect. Check the relative paths. (use ./ instead of /)

3. Sorting issues:

1. Check the store configuration (sortInfo and sort type) or use setDefaultSort()
PHP Code:
sortInfo:{field'fieldname'direction'ASC'
//or call:
store.setDefaultSort('fieldname''ASC');
2. Also check if the sort type was set.
3. If it’s only sorting the current page and you want to sort on entire database query then remoteSort should be set to true (remoteSort defaults to local sorting)

4. Grids inside Tab Panels

• A GridPanel is like any other panel, you can add it directly as an item to a tab
• Make sure the Grid Panel IS the Tab Panel (Grid is a panel component already so there is no need to wrap it with another panel).
• Set layoutOnTabChange on the Tab Panel (Set to true to do a layout of tab items as tabs are changed.)
Code:
var g = new Ext.grid.GridPanel(....); //grid object

var tabs2 = new Ext.TabPanel({
renderTo: document.body,
activeTab: 0,
width:'100%',
height:150,
frame:true,
defaults:{autoScroll: true},
items:[g] //the grid object

1. Define a custom renderer or
2. You could use the rowselect event of Ext.grid.RowSelectionModel. You might do something like this:
Code:
function handleRowSelect(selectionModel, rowIndex, selectedRecord) {
//assuming the record has a field named 'url' or build it as you need to
var url = selectedRecord.get('url');
//if you want to open another window
window.open(url);
}
grid.getSelectionModel().on('rowselect', handleRowSelect);

6. Combining Fields into One Column:

1. Concatenate the two elements in the Record definition.
Code:
//combine two fields into one
//the first field does not have obj.
//any additional fields that are combined use a preceding obj.
//sorting will be by the first field specified (first_name in this example)
{name: 'full_name', type: 'string', mapping: 'first_name + " " + obj.last_name'},
{name: 'age'}
]);

var grid = new Ext.grid.GridPanel({
store: new Ext.data.Store({
data: Ext.grid.dummyData
}),

columns: [
]
});
2. The convert function in a field definition now receives in the second parameter the whole of the data object that is being used to create the Record, so you can create any value you like in a field.
3. For another alternative that allows sorting on the resulting "calculated" field see this thread

7. How to modify appearance, behavior of specific rows or columns?

• You can use a function of your own to add a CSS class name of your own choosing a Grid row depending upon the data in the underlying Record object.
• Specify an id in the column model for each field that you would like to modify. A CSS class will be generated in the form x-grid3-td-{COLUMNID}. For example the array-grid example has a column with an id of 'company'. If you wanted to change the cursor to be a text cursor add this css after the core css is loaded:
HTML Code:
.x-grid3-td-company {
cursor: text;
}
• Override the getRowClass
• Use a function in the Grid's View and return a class name string.
Code:
gridView = new Ext.grid.GridView({
//forceFit: true,
getRowClass : function (row, index) {
var cls = '';
var data = row.data;
switch (data.SEVERITY) {
case 'C' :
cls = 'alarmGridCritical'
break;
case 'M' :
cls = 'alarmGridMinor'
break;
}
return cls;
}
});
• See example here.

8. How to add click handlers to specific Grid cells?

• Add a listener for the Grid's cellclick event. The listener is passed the row and column indexed clicked on. The column index may be used to determine which field was clicked on (Columns may be reordered by the user so using the column index as the field index is unsafe).
• A cellclick event handler must find the relevant information like this:
Code:
function(grid, rowIndex, columnIndex, e) {
var record = grid.getStore().getAt(rowIndex); // Get the Record for the row
// Get field name for the column
var fieldName = grid.getColumnModel().getDataIndex(columnIndex);
var data = record.get(fieldName);
}

9. Store is empty even after calling load() on my Store

• Store.load() is asynchronous when using remote data (through an HttpProxy, or a ScriptTagProxy).
• It returns immediately after the request is sent to the server and continues to process code without waiting. To control postprocessing of returned data, use a callback to the load call, or add listeners to the Store's "load" and "loadexception"] (most problems will be indicated here) events.
• PHP Code:
alert(myStore.getCount());// no way!  won't work.  the store was just requested, it's not 'back' from the server yet.

myStore.on({

fn: function(storerecordsoptions){

//store is loaded, now you can work with it's records, etc.

console.log('Data Store listener fired (load), arguments:',arguments);

console.log('Store count = ',store.getCount());
}
,
scope:this

10. Make grid resize with the window

11. Updating a cell (actually the store)

• You actually update the store, not a cell:
Code:
var record = editorGridPanel.getStore().getAt(row);
record.set('fieldname', newValue);
• If this Field is an editor, you can collect the Grid cell's value in a beforeedit event handler (see Listeners in following post). See getSelectedCell in API docs.
• If using mouseover:
Code:
grid.on("mouseover", function(e, t) {
var row;
if((row = this.findRowIndex(t)) !== false){
var record = this.store.getAt(row);
var id = record.get('Id');
}
}, grid);

12. How to reload a Grid from a different URL?
Usually, this question means that different '''parameters''' need to be passed to the same server script. The answer is "Do not embed parameters in the DataProxy's URL"

Code:
var proxy = new Ext.data.HttpProxy({
url: '/DoSearch.php'
});
// Add the HTTP parameter searchTerm to the request
params.searchTerm = searchValue;
});

13. XML Issues

• Many people will recommend you use JSON.
Xml has a huge performance penalty associated with it, and JSON is just plain simpler (and therefore much easier to manipulate).
• If there is a specific requirement for xml, check if your server setting the right content-type for the xml (Response.ContentType = "text/xml"). For example have the server return the correct mime type for the XML document:
Code:
<mime-mapping>
<extension>xml</extension>
<mime-type>text/xml</mime-type>
</mime-mapping>

14. Grid still shows records even when it should be empty

• Check that you are return an empty array and not null in the response from your server.
The store will get updated with an empty array, thus showing nothing.
If you return null then the grid doesn't get updated (the store's data has not changed).

15. How to debug the response going into JsonReader

• In firebug, go to ext-all-debug.
• find "getJsonAccessor: function(){"
• Scroll up a bit to read, set a breakpoint there, and reload the page

16. How to drag/drop/reorder rows?

17. Horizontal scrolling issues

• If you have a GridPanel with horizontall scroll and when go to another page the horizontal scroll reverts to the left side position you can try this code to prevent it from scrolling back:
Code:
grid.getStore().on({
this.prevScrollState = this.getScrollState();
this.prevScrollState.top = 0;
},
this.restoreScroll(this.prevScrollState);
remove this.prevScrollState;
},
scope: grid.getView()
});

18. Mixing fixed width and variable width columns

Imagine a scenario where there are columns 'Salutation' and 'Name' which needs to be at 50px width each, and a column 'notes' which should be sized to the grid's size.

• Solution 1:
Set a width for 'Salutation' and 'Name'.
Give an "id" to the 'notes' column and use the autoExpandColumn config option of the GridPanel. The Array grid example in the examples/grid/array-grid.js does just this. Price, Change, % Change, and Last Updated are all fixed width. Company will stretch to fit the rest of the size available. Notice that it has an "id" NOT a dataIndex. The autoExpandColumn config only takes id's, not dataIndex's.
• Solution 2:
Try: viewConfig:{forceFit:true}

19. How to hide a column

1. Navigate to: http://extjs.com/deploy/dev/examples/grid/array-grid.html
2. In Firebug's console type: Ext.getCmp('ext-comp-1001').getColumnModel().setHidden(0, true)
1. Ext.getCmp('ext-comp-1001') returns the GridPanel object.
2. getColumnModel() gets it's column model.
3. setHidden(0, true) hides column 0 (0 = the first column).

20. How to wrap contents within a cell of a fixed width grid column?
The goal is to have the contents of a cell automatically wrap into a fixed defined width according to the column definition instead of having to manually drag the column width to expand the column.

1. Give the column you want to wrap an ID:
http://extjs.com/deploy/dev/docs/?class=Ext.grid.ColumnModel&member=id
2. Then define CSS classes like this:
Code:
overflow: hidden;
}
white-space: normal;
}

If you want to apply this to the entire grid apply it to the basic td class of the grid.

21. How to add a column with tools for each record?

• Approach 1
http://extjs.com/deploy/dev/examples/grid/array-grid.js
2. Add an extra column to the column model definition and a custom renderer.
Code:
width: 60,
sortable: false,
renderer: function() {
return '<div class="controlBtn"><img src="../shared/icons/fam/cog_edit.png" width="16" height="16" class="control_edit"><img src="../shared/icons/fam/folder_go.png" width="16" height="16" class="control_go"></div>';
},
dataIndex: 'company'}
3. Then you would setup an event handler on the click event.
PHP Code:
grid.on('click', function(e) {
var
btn e.getTarget('.controlBtn');
if (
btn) {
var
e.getTarget();
var
this.view;
var
rowIdx v.findRowIndex(t);
var
record this.getStore().getAt(rowIdx);
var
control t.className.split('_')[1];
switch (
control) {
case
'edit':

console.log('edit this record - ' record.id);
break;
case
'go':

console.log('go to this record - ' record.id);
break;
}
}
},
grid);

Add the following CSS rule in array-grid.html to give some padding and change the cursor.

HTML Code:
<style>
.controlBtn img {
cursor: pointer;
}
</style>
4. Using this same method you could add as many tools as you would like in the controls section and always give them the css class "controls_{toolname}". Ideally you would break this out into an XTemplate so that you could simply pass in whatever tools you would like to use and output them on the grid as well.
5. Approach 2 utilizes a plugin as discussed here:
PHP Code:
// vim: ts=4:sw=4:nu:fdc=2:nospell
/**
* RowAction plugin for Ext grid
*
* Contains renderer for an icon and fires events when icon is clicked
*
* @author    Ing. Jozef Sakalos <jsakalos at aariadne dot com>
* @date      December 29, 2007
* @version   $Id: Ext.ux.grid.RowAction.js 126 2008-01-31 03:33:50Z jozo$
*
* the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
* that the code/component(s) do NOT become part of another Open Source or Commercially
* licensed development library or toolkit without explicit permission.
*
*/

Ext.ns('Ext.ux.grid');

/**
* @class Ext.ux.grid.RowAction
* @extends Ext.util.Observable
*
* Creates new RowAction plugin
* @constructor
* @param {Object} config The config object
*
* @cfg {String} iconCls css class that defines background image
*/
Ext.ux.grid.RowAction = function(config) {

Ext.apply(thisconfig);

/**
* @event beforeaction
* Fires before action event. Return false to cancel the subsequent action event.
* @param {Ext.grid.GridPanel} grid
* @param {Ext.data.Record} record Record corresponding to row clicked
* @param {Integer} rowIndex
*/

beforeaction:true

/**
* @event action
* Fires when icon is clicked
* @param {Ext.grid.GridPanel} grid
* @param {Ext.data.Record} record Record corresponding to row clicked
* @param {Integer} rowIndex
*/

,action:true

});

Ext.ux.grid.RowAction.superclass.constructor.call(this);
};

Ext.extend(Ext.ux.grid.RowActionExt.util.Observable, {

,sortable:false

,dataIndex:''

,width:20

,fixed:true

,lazyRender:true

,iconCls:''

// private - plugin initialization

,init:function(grid) {

this.grid grid;
var
view grid.getView();

grid.on({

render:{scope:thisfn:function() {

view.mainBody.on({

click:{scope:thisfn:this.onClick}
});
}}
});
if(!
this.renderer) {

this.renderer = function(valuecellrecordrowcolstore) {

cell.css += (cell.css ' ' '') + 'ux-grid3-row-action-cell';
var
retval '<div class="' this.getIconCls(recordrowcol) + '"';

retval += this.style ' style="' this.style '"' '';

retval += this.qtip ' ext:qtip="' this.qtip +'"' '';

retval += '> </div>';
return
retval;
}.
createDelegate(this);
}
}
// eo function init

// override for custom processing
,getIconCls:function(recordrowcol) {
return
this.boundIndex record.get(this.boundIndex) : this.iconCls;
}
// eo function getIconCls

// private - icon click handler
,onClick:function(etarget) {
var
recordiconCls;
var
row e.getTarget('.x-grid3-row');
var
col this.grid.getView().getCellIndex(e.getTarget('.ux-grid3-row-action-cell'));

if(false !== row && false !== col) {

record this.grid.store.getAt(row.rowIndex);

iconCls this.getIconCls(recordrow.rowIndexcol);
if(
Ext.fly(target).hasClass(iconCls)) {
if(
false !== this.fireEvent('beforeaction'this.gridrecordrow.rowIndex)) {

this.fireEvent('action'this.gridrecordrow.rowIndexe);
}
}
}
}
// eo function onClick
});

// eof

22. How to center elements in a toolbar?

1. PHP Code:
myToolbar.getEl().child("table").wrap({tag:'center'})
2. PHP Code:
var myGridPanel.getBottomToolbar().el;
var
t.createChild("<center></center>");
c.appendChild(t.child("table"));

23. How to delete all selected rows?

1. PHP Code:
Ext.each(contactgrid.getSelectionModel().getSelections(), contactgrid.getStore().removecontactgrid.getStore());
2. PHP Code:
tbar: [
{

text'Delete Contacts',

iconCls:'remove',

handler : function(t){

console.log('   inside "Delete Contacts" with arguments = ',arguments);

grid contactgrid;

//get the store associated with the grid:

store grid.getStore();

//returns array of record objects for selected rows (all info for row)

var selections grid.selModel.getSelections();

console.log('        grid    = ',grid);

console.log('        selections    = ',selections);

var selections.length;

for(var 0ni++){

console.log('  Number Selected =',n);

console.log('  selections =',selections);

console.log('  store before remove attempt #',i,': ',store,' store has ',store.getCount(),' records');

store.remove(selections[i]);

console.log('  store after remove attempt #',i,': ',store,' store has ',store.getCount(),' records');
}
//end for

}//end handler

}//end Delete Contacts

24. Issues with paging or total record count

• Paging is typically handled on the server side.
• The idea is to reduce the amount of data exchanged with the client.
• Pass the paging requirements to the server when the store is loaded.
PHP Code:
bbar: new Ext.PagingToolbar({

pageSize25//when you go to next page I believe it uses this number
...
})

//or if you want to use autoLoad in the store's configuration:

• Check using Firebug what all is sent out in the POST and retrieve that information server side to generate the necessary sql to return the appropriate data. Something to the effect of:
PHP Code:
/* By specifying the start/limit params in ds.load
* the values are passed here
* if using ScriptTagProxy the values will be in $_GET * if using HttpProxy the values will be in$_POST (or $_REQUEST) * the following two lines check either location, but might be more * secure to use the appropriate one according to the Proxy being used */$start = (integer) (isset($_POST['start']) ?$_POST['start'] : $_GET['start']);$end = (integer) (isset($_POST['limit']) ?$_POST['limit'] : $_GET['limit']); //check for the 'sort' and 'dir' in the POST array.$sortDir = isset($_POST['dir']) ?$_POST['dir'] : 'ASC';//default to ASC if not set

$sortBy = isset($_POST['sort']) ? $_POST['sort] : 'company';//default to company name if not set$sql_count = 'SELECT FROM ' . $table;$sql = $sql_count . ' ORDER BY ' .$sortBy. ' ' . $sortDir . ' LIMIT ' .$start . ', '. $end;$result_count = mysql_query($sql_count);$rows = mysql_num_rows(\$result_count);

25. Get a record from the grid by row index

Code:
var record = grid.getStore().getAt(rowIndex);

26. Load data to a grid from two diferent server calls/stores

1. Adding records from Store 2 to Store 2.
PHP Code:
var store2 = new Ext.data.Store({
...
});
var
store1 = new Ext.data.Store({
...

listeners: {

}
}
});
2. Using records from Store 2 with Store 1.
For example, the first data col comes from Store 1 and the data from Store 2 forms cols 2 and 3. You can use a renderer that finds the data in the second store if the 'other' columns are just 'lookup' data, e.g.:

PHP Code:
var store1 = new Ext.data.Store({
...,

fields: ['field1''field2']
});

var store2 = new Ext.data.Store({
...

id'field2',

fields: ['field2''fieldA''fieldB']
});

var renderA = function(value) {
var
rec store2.getById(value);
return
rec rec.get('fieldA') : '';
}
var
renderB = function(value) {
var
rec store2.getById(value);
return
rec rec.get('fieldB') : '';
}

var columns = [
{
{
{
];

27. "Auto size" columns to the largest element in them

28. Disable editing of particular rows

• Use beforeedit and return false to stop the edit
PHP Code:
var grid = new Ext.grid.EditorGridPanel({
...

isCellEditable: function(colIndexrowIndex) {
var
field this.getColumnModel().getDataIndex(colIndex);
if (
field == 'value') {
var
record this.getStore().getAt(rowIndex);
if (!
record.get('enable_edit').getValue()) { //enable_edit is field in record

return false;//return false to deny editing

}
}
return
Ext.grid.EditorGridPanel.prototype.isCellEditable.call(thiscolIndexrowIndex);
}
});
• Option/Example 2
PHP Code:
myColumnModel.isCellEditable = function(colIndexrowIndex){ return !someBooleanStoredSomewhere; };
• Option/Example 3
PHP Code:
this.on('beforeedit'Comment.Methods.commentUpdateCheckPermission);

commentUpdateCheckPermission : function (commentData) {
if (
cds.data.items[commentData.row].data.user_ID != Ext.util.Format.uppercase(VMOC.myUUID)) {

Ext.MessageBox.alert('Permission denied''You do not have permission to edit this comment.');

cds.rejectChanges();

commentData.cancel true;
}
}

29. What is difference between contentEl, applyTo and renderTo?
For most use cases you should be able to use the contentEl config option with a div in your markup with a css class of x-hidden.

• contentEl - This config option is used to take existing content and place it in the body of a new panel. It is not going to be the actual panel itself. (It will actually copy the innerHTML of the el and use it for the body). You should add either the x-hidden or the x-hide-display CSS class to prevent a brief flicker of the content before it is rendered to the panel.
• applyTo - This config option allows you to use pre-defined markup to create an entire Panel. By entire, I mean you can include the header, tbar, body, footer, etc. These elements must be in the correct order/hierarchy. Any components which are not found and need to be created will be autogenerated.
• renderTo - This config option allows you to render a Panel as its created. This would be the same as saying myPanel.render(ELEMENT_TO_RENDER_TO);

30. Dirty Record / Red Flag (modifying, etc.)

1. To disable "dirty cell mark" for a record field. Use the following line when you modify a cell you do not wish to have a "dirty" marker. This will get the record to think that this cell has not been modified without having to commit the entire record.
PHP Code:
record.modified[this.dataIndex] = undefined// will prevent a "dirty" flag to be displayed on the check box
2. To remove the red triangle only from some records (not all), hook into the grid's validateedit event and cancel it if the edit occurred on a targeted row, then set the field's new value in the Record directly:
PHP Code:
grid.on('validateedit', function(e) {
var
myTargetRow 6;

if (e.row == myTargetRow) {

e.cancel true;

e.record.data[e.field] = e.value;
}
})

3. Change the cell style back to the one without the little red corner and update the data store with the new value (Does not execute an XHR to send/commit data to the server.)
PHP Code:
grid.on('afteredit'afterEditthis );
function
afterEdit(val) {

val.record.commit();
};
4. Change the CSS to never show the dirty flag:
PHP Code:
.x-grid-dirty-cell {

background-image:none;

Or:

PHP Code:

<style type="text/css">
.
x-grid3-td-[id-of-column] {background-image:none!important;}
</
style

posted @ 2008-05-23 09:17 meetrice 阅读(...) 评论(...) 编辑 收藏