PDA

View Full Version : problem with propertyGrid, different-type-cell in different rows



aj3423
25 Jun 2009, 4:03 AM
Hello there,
I'm using a property to show some user data, like:

'username'
'sex'
'marriage'
...

so the second row 'sex' is a combobox to choose 'male' or 'female'
(in my combo.store, '1' means male, '0' means female)
the third row 'marriage' is a checkbox to check 'yes' or 'no'
but in propertyGrid, the 'sex' combo displays '1' instead of 'male',
and the 'marriage' checkbox doesn't display, there appears a 'true' string.
How can I solve that.
Thanks.

Condor
25 Jun 2009, 4:20 AM
You need to specify the customEditors config option with editors for sex and marriage properties.

Condor
25 Jun 2009, 4:27 AM
ps. PropertyGrid is a bit limited in it's possibilities. Sometimes you have to use an EditorGridPanel instead (see example here (http://extjs.com/forum/showthread.php?p=141782#post141782)).

aj3423
28 Jun 2009, 8:11 AM
Thanks, I tried the 'customEditors' but failed to get work, I did lots of searching, seems no one has met this problem.. after try and try for 2 days, I found this tricky way:

override GridView's doRender

doRender : function(cs, rs, ds, startRow, colCount, stripe){
//debugger;
var ts = this.templates, ct = ts.cell, rt = ts.row, last = colCount-1;
var tstyle = 'width:'+this.getTotalWidth()+';';
// buffers
var buf = [], cb, c, p = {}, rp = {tstyle: tstyle}, r;
for(var j = 0, len = rs.length; j < len; j++){
r = rs[j]; cb = [];
var rowIndex = (j+startRow);
for(var i = 0; i < colCount; i++){
c = cs[i];
p.id = c.id;
p.css = i == 0 ? 'x-grid3-cell-first ' : (i == last ? 'x-grid3-cell-last ' : '');
p.attr = p.cellAttr = "";
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);

p.style = c.style;
if(i === last) {
var editor = this.grid.getColumnModel().getCellEditor(i, rowIndex);
var cell = editor.field;
var xType = cell? cell.getXType ? cell.getXType() : null : null;

switch(xType) {
case 'combo':
var df = cell.displayField;
var vf = cell.valueField;
var reci = cell.store.find(vf, p.value);
var rec = cell.store.getAt(reci);

p.value = rec ? rec.get(df) : cell.emptyText;
break;
case 'colorfield':
p.value = ''
p.style += ' background-color: #' + rs[j].data.value || cell.curColor + ';';
break;
case 'checkbox':
//p.css = how to do with the checkbox?....
//debugger;

break;
default:
break;
}
}
if(p.value == undefined || p.value === "") p.value = " ";
if(this.markDirty && r.dirty && typeof r.modified[c.name] !== 'undefined'){
p.css += ' x-grid3-dirty-cell';
}
cb[cb.length] = ct.apply(p);
}
var alt = [];
if(stripe && ((rowIndex+1) % 2 == 0)){
alt[0] = "x-grid3-row-alt";
}
if(r.dirty){
alt[1] = " x-grid3-dirty-row";
}
rp.cols = colCount;
if(this.getRowClass){
alt[2] = this.getRowClass(r, rowIndex, rp, ds);
}
rp.alt = alt.join(" ");
rp.cells = cb.join("");
buf[buf.length] = rt.apply(rp);
}
return buf.join("");
}

Condor
28 Jun 2009, 10:33 PM
That is a horrible solution! You should have overridden the renderCell method (inline!) of PropertyColumnModel to return a specific renderer for the sex and marriage properties.

chrizmaster
13 Jul 2009, 1:19 AM
It would be awesome to have a complete example of how to put in comboboxes plus how to add checkboxes.

I tried for 2 days but finally throw my computer out of the window (with the window closed...)

I can'T do this often cause it's to expensive...^^

Chriz

Condor
13 Jul 2009, 1:56 AM
OK, you asked for it (but be warned, it isn't that simple):

var checkColumn = new Ext.ux.grid.CheckColumn({
dataIndex: 'value'
});
var comboStore = new Ext.data.ArrayStore({
id: '0',
fields: ['value', 'text'],
data: [[1, 'One'], [2, 'Two'], [3, 'Three']]
});
var propGrid = new Ext.grid.PropertyGrid({
source: {
'combo': 1,
'check': false
},
customEditors: {
'combo': new Ext.grid.GridEditor(new Ext.form.ComboBox({
store: comboStore,
valueField: 'value',
displayField: 'text',
mode: 'local',
triggerAction: 'all'
}), {})
},
plugins: [checkColumn],
initComponent: function(){
this.constructor.prototype.initComponent.apply(this, arguments);
Ext.apply(this.getColumnModel(), {
isCellEditable: function(colIndex, rowIndex){
var r = this.store.store.getAt(rowIndex);
// Check column doesn't have an editor -> not editable
if(r.get('name') == 'check'){
return false;
}
return this.constructor.prototype.isCellEditable.apply(this, arguments);
},
renderCellDelegate : (function(val, meta, r){
// Return checkbox markup
if(r.get('name') == 'check'){
return checkColumn.renderer.apply(this, arguments);
}
// Return combobox text for value
if(r.get('name') == 'combo'){
return comboStore.getById(val).get('text');
}
return this.constructor.prototype.renderCell.apply(this, arguments);
}).createDelegate(this.getColumnModel())
});
}
});

chrizmaster
13 Jul 2009, 2:36 AM
thank you.

just a short question. Arraystore is part of extjs 3. I am still using extjs 2

So I can use the simplestore right?

Chriz

Condor
13 Jul 2009, 2:38 AM
Yes (but the example was tested on 3.0+, so I'm not 100% sure if it works on Ext 2.2.1).

aj3423
8 Aug 2009, 11:12 PM
var propGrid = new Ext.grid.PropertyGrid({
source: {
'combo': 1,
'check': false,
'date': ''
},
customEditors: {
'check': new Ext.grid.GridEditor(new Ext.form.Checkbox()),
'combo': new Ext.grid.GridEditor(new Ext.form.ComboBox({
store: comboStore,
valueField: 'value',
displayField: 'text',
mode: 'local',
triggerAction: 'all'
}), {}),
'date': new Ext.grid.GridEditor(new Ext.form.DateField(), {})
},
initComponent: function() {
this.constructor.prototype.initComponent.apply(this, arguments);
Ext.apply(this.getColumnModel(), {
renderCellDelegate: (function(val, meta, r, row, col) {
var editor = this.getCellEditor(col, row);
var cell = editor.field;
var xType = cell? cell.getXType ? cell.getXType() : null : null;

console.info('row='+row+', col='+col+', xType=' + xType + ', val=' + val);
switch(xType) {
case 'combo':
var rec = cell.store.getById(val);
return rec.get(cell.displayField);
case 'colorfield':
//return
//p.value = ''
//p.style += ' background-color: #' + rs[j].data.value || cell.curColor + ';';
break;
case 'checkbox':
default:
return this.constructor.prototype.renderCell.apply(this, arguments);
}
}).createDelegate(this.getColumnModel())
});
}
});

this code works well with any normal text, but if the cell is something like a color field(render the hole cell with a color, not text), the renderCellDelegate cannot help, so it still need to do some tricky thing in GridView's doRender?
Thanks.