PDA

View Full Version : SelectEditor Question



dmayer
25 Oct 2006, 5:30 AM
Jack,

I am using the selecteditor for the yui grid and I was wondering how I can store the option value a user has selected from the selecteditor box but still show the option text in the grid.

Here's my reasoning, after the user updates the cell, I want to update my backend database with the option value not the option text.

How can I do this?

jack.slocum
25 Oct 2006, 7:31 AM
You can put a renderer on the column. The renderer could even reference the same select and look up the option. I would recommend closuring it (like below) instead of looking it up every time (expensive).



var myOptions = document.getElementById('my-select').options;
var myRender = function(value){
return myOptions[value].text;
}


Then assign myRender to the column in your column model config with renderer:myRender.

dmayer
25 Oct 2006, 9:50 AM
Jack,

I having a small problem with implementing the renderer and the cell preprocessor.

Here's some background on the problem:
I created a yui-ext.select widget that is modeled after the yui-ext-grid. My select widget resuses the grid datamodel object. In my example, the select widget utilizes a jsondatamodel to load data from a php file.

The problem is that both the select widget and the grid use the yui event manager to initialize after the window load event happens. When the grid goes to execute the cell preprocessor, the select options have not completely rendered. How can I make this work?

Here is my code:

TaskGrid.js



TaskGrid = function(){
var gridDataModel;
var grid;
var colModel;

var formatMoney = function(value){
value -= 0;
value = (Math.round(value*100))/100;
value = (value == Math.floor(value)) ? value + '.00' : ( (value*10 == Math.floor(value*10)) ? value + '0' : value);
return "$" + value;
};

var formatBoolean = function(value){
return value ? 'Yes' : 'No';
};

var formatDate = function(value){
//var d = new Date(value);
//return d.dateFormat('m/d/Y');
return value.dateFormat('m/d/Y');
};

var parseDate = function(value){
return new Date(Date.parse(value));
};
var parseStatusID = function(value){
return new Date(Date.parse(value));
};

var myRender = function(value){
var statusselect = document.getElementById('statuslist').options;
var myval;
for (var i = 0; i<statusselect.length; i++) {
if (statusselect[i].value == value) {
myval = statusselect[value].text;
}
}

//return statusoptions[value].text;
return myval;
}

return {
init : function(){



var schema = {
root: 'tasks',
id: 'id',
fields: ['id', 'name', 'categoryID', 'categoryName', 'contactID', 'creationDate', 'description', 'dueDate',
'modificationDate', 'statusID', 'statusDate']
};
var gridDataModel = new YAHOO.ext.grid.JSONDataModel(schema);

gridDataModel.addPreprocessor(9, myRender);
//gridDataModel.addPostprocessor(2, parseCategoryID);
gridDataModel.addPreprocessor(5, parseDate);
gridDataModel.addPreprocessor(7, parseDate);
gridDataModel.addPreprocessor(8, parseDate);
gridDataModel.addPreprocessor(10, parseDate);

gridDataModel.setDefaultSort(colModel, 0, "DESC");

var yg = YAHOO.ext.grid;
var cols = [{
header: "ID",
width: 25,
dataIndex: 0
},{
header: "Name",
width: 130,
dataIndex: 1,
editor: new yg.TextEditor({allowBlank: true})
},{
header: "Category",
width: 95,
dataIndex: 3,
editor: new yg.SelectEditor('categories')
},{
header: "ContactID",
width: 95,
dataIndex: 4
},{
header: "CreationDate",
width: 95,
dataIndex: 5,
renderer: formatDate,
editor: new yg.DateEditor({format: 'm/d/Y', minValue: '01/01/06'})
},{
header: "Description",
width: 70,
dataIndex: 6,
editor: new yg.TextEditor({allowBlank: true})
},{
header: "Due Date",
width: 95,
dataIndex: 7,
renderer: formatDate,
editor: new yg.DateEditor({format: 'm/d/Y', minValue: '01/01/06'})
},{
header: "Modification Date",
width: 95,
dataIndex: 8,
renderer: formatDate,
editor: new yg.DateEditor({format: 'm/d/Y', minValue: '01/01/06'})
},{
header: "Status",
width: 95,
dataIndex: 9,
renderer: myRender,
editor: new yg.SelectEditor('statuslist')
},{
header: "Status Date",
width: 55,
dataIndex: 10,
renderer: formatDate,
editor: new yg.DateEditor({format: 'm/d/Y', minValue: '01/01/06'})
}];

var colModel = new YAHOO.ext.grid.DefaultColumnModel(cols);
colModel.defaultSortable = true;

this.grid = new YAHOO.ext.grid.EditorGrid('grid', gridDataModel, colModel);
this.grid.render();
this.grid.autoSizeHeaders = true;
gridDataModel.load('gettasks.php');

}
};
} ();

function buildGrid() {
StatusSelect.init();
CategorySelect.init();
TaskGrid.init();
}

YAHOO.util.Event.on(window, 'load', buildGrid);



DropDown.js



YAHOO.namespace('ext.dropdown');

YAHOO.ext.dropdown.DropDown = function(container, selectid, dataModel, colModel, selectClass){

this.container = YAHOO.ext.Element.get(container);

/** @private */
this.id = selectid;


/**@private*/
//this.domID = domID;
this.dataModel = dataModel;
/** @private */
this.colModel = colModel;
this.selectClass = selectClass;
};

YAHOO.ext.dropdown.DropDown.prototype = {

render : function(){

var select = document.createElement("select");
select.id = this.id;
select.className = this.selectClass;
select.style.visibility = 'hidden';
var dropdowndiv = document.getElementById(this.container.id);
dropdowndiv.appendChild(select);
//var body = document.getElementsByTagName('body');
//document.body.appendChild(select);
this.select = select;

this.view = new YAHOO.ext.dropdown.DropDownView();
this.view.init(this);
this.el = getEl(this.view.render(), true);

},

};

StatusSelect = function () {
var sel;

return {
init : function(){

var schema = {
root: 'status',
id: 'id',
fields: ['id', 'name']
};
var selectDataModel = new YAHOO.ext.grid.JSONDataModel(schema);

selectDataModel.load('getstatuslist.php');

var cols = [{
header: "ID",
width: 25,
dataIndex: 0
},{
header: "Name",
width: 130,
dataIndex: 1,
}];

var selectColModel = new YAHOO.ext.grid.DefaultColumnModel(cols);
this.sel = new YAHOO.ext.dropdown.DropDown('dropdowns', 'statuslist', selectDataModel, selectColModel, 'dropdown');
this.sel.render();

}

};
} ();


CategorySelect = function () {
var sel;

return {
init : function(){

var schema = {
root: 'categories',
id: 'id',
fields: ['id', 'name']
};
var selectDataModel = new YAHOO.ext.grid.JSONDataModel(schema);

selectDataModel.load('getcategories.php');

var cols = [{
header: "ID",
width: 25,
dataIndex: 0
},{
header: "Name",
width: 130,
dataIndex: 1,
}];

var selectColModel = new YAHOO.ext.grid.DefaultColumnModel(cols);
this.sel = new YAHOO.ext.dropdown.DropDown('dropdowns', 'categories', selectDataModel, selectColModel, 'dropdown');
this.sel.render();

}

};
} ();

/*
* YUI Extensions
* Copyright(c) 2006, Jack Slocum.
*
* This code is licensed under BSD license.
* http://www.opensource.org/licenses/bsd-license.php
*/

/**
* @class
* Default UI code used internally by the Grid. Documentation to come.
* @constructor
*/
YAHOO.ext.dropdown.DropDownView = function(){
/** @private */
this.dropdown = null;

};

YAHOO.ext.dropdown.DropDownView.prototype = {
init: function(dropdown){
this.dropdown = dropdown;
},

/**
* Utility method that gets an array of the cell renderers
*/
getColumnRenderers : function(){
var renderers = [];
var cm = this.dropdown.colModel;
var colCount = cm.getColumnCount();
for(var i = 0; i < colCount; i++){
renderers.push(cm.getRenderer(i));
}
return renderers;
},

buildIndexMap : function(){
var colToData = {};
var dataToCol = {};
var cm = this.dropdown.colModel;
for(var i = 0, len = cm.getColumnCount(); i < len; i++){
var di = cm.getDataIndex(i);
colToData[i] = di;
dataToCol[di] = i;
}
return {'colToData': colToData, 'dataToCol': dataToCol};
},

getDataIndexes : function(){
if(!this.indexMap){
this.indexMap = this.buildIndexMap();
}
return this.indexMap.colToData;
},

getColumnIndexByDataIndex : function(dataIndex){
if(!this.indexMap){
this.indexMap = this.buildIndexMap();
}
return this.indexMap.dataToCol[dataIndex];
},

setCSSWidth : function(colIndex, width, pos){
var selector = ["#" + this.dropdown.id + " .ygrid-col-" + colIndex, ".ygrid-col-" + colIndex];
YAHOO.ext.util.CSS.updateRule(selector, 'width', width + 'px');
if(typeof pos == 'number'){
YAHOO.ext.util.CSS.updateRule(selector, 'left', pos + 'px');
}
},

updateColumns : function(){
var colModel = this.dropdown.colModel;
var colCount = colModel.getColumnCount();
var pos = 0;
var totalWidth = colModel.getTotalWidth();
for(var i = 0; i < colCount; i++){
if(colModel.isHidden(i)) continue;
var width = colModel.getColumnWidth(i);
this.setCSSWidth(i, width, pos);
pos += width;
}
this.lastWidth = totalWidth;
},

getOptionList : function(){
return this.bwrap.dom;
},

insertRows : function(dataModel, firstRow, lastRow){
// Get the renders from the column model. I need this
var renderers = this.getColumnRenderers();
var dindexes = this.getDataIndexes();

// Get the number of columns. Not sure if this will apply to the select element
var colCount = this.dropdown.colModel.getColumnCount();

for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
this.renderOption(dataModel, rowIndex, renderers, dindexes);
}
},

renderOption : function(dataModel, rowIndex, renderers, dindexes){
// Append option tags to the select element
var html = '<option>{1}</option>';
var tpl = new YAHOO.ext.DomHelper.Template(html);

var val = renderers[0](dataModel.getValueAt(rowIndex, dindexes[1]), rowIndex, 0);
if(val == '') val = '';
tpl.append(this.dropdown.select, [dataModel.getRowId(rowIndex), val]);
//tpl.append(this.dropdown.select, [val, val]);
},


updateRows : function(dataModel, firstRow, lastRow){
var bt = this.getBodyTable();
var dindexes = this.getDataIndexes();
var renderers = this.getColumnRenderers();
var colCount = this.dropdown.colModel.getColumnCount();
for(var rowIndex = firstRow; rowIndex <= lastRow; rowIndex++){
var row = bt.rows[rowIndex];
var cells = row.childNodes;
for(var colIndex = 0; colIndex < colCount; colIndex++){
var td = cells[colIndex];
var val = renderers[colIndex](dataModel.getValueAt(rowIndex, dindexes[colIndex]), rowIndex, colIndex);
if(val == '') val = '';
td.firstChild.innerHTML = val;
}
}
},


getRowHeight : function(){
if(!this.rowHeight){
var rule = YAHOO.ext.util.CSS.getRule(["#" + this.dropdown.id + " .ygrid-row", ".ygrid-row"]);
if(rule && rule.style.height){
this.rowHeight = parseInt(rule.style.height, 10);
}else{
this.rowHeight = 21;
}
}
return this.rowHeight;
},

renderRows : function(dataModel){
if(this.dropdown.selModel){
this.dropdown.selModel.clearSelections();
}
this.rowHeight = this.getRowHeight();
this.insertRows(dataModel, 0, dataModel.getRowCount()-1);
},

calcColumnWidth : function(colIndex, maxRowsToMeasure){
var maxWidth = 0;
var bt = this.getBodyTable();
var rows = bt.childNodes;
var stopIndex = Math.min(maxRowsToMeasure || rows.length, rows.length);
if(this.dropdown.autoSizeHeaders){
var h = this.headers[colIndex];
var curWidth = h.style.width;
h.style.width = this.dropdown.minColumnWidth+'px';
maxWidth = Math.max(maxWidth, h.scrollWidth);
h.style.width = curWidth;
}
for(var i = 0; i < stopIndex; i++){
var cell = rows[i].childNodes[colIndex].firstChild;
maxWidth = Math.max(maxWidth, cell.scrollWidth);
}
return maxWidth + /*margin for error in IE*/ 5;
},

autoSizeColumn : function(colIndex, forceMinSize){
if(forceMinSize){
this.setCSSWidth(colIndex, this.dropdown.minColumnWidth);
}
var newWidth = this.calcColumnWidth(colIndex);
this.dropdown.colModel.setColumnWidth(colIndex,
Math.max(this.dropdown.minColumnWidth, newWidth));
this.dropdown.fireEvent('columnresize', colIndex, newWidth);
},

autoSizeColumns : function(){
var colModel = this.dropdown.colModel;
var colCount = colModel.getColumnCount();
var wrap = this.wrap;
for(var i = 0; i < colCount; i++){
this.setCSSWidth(i, this.dropdown.minColumnWidth);
colModel.setColumnWidth(i, this.calcColumnWidth(i, this.dropdown.maxRowsToMeasure), true);
}
if(colModel.getTotalWidth() < wrap.clientWidth){
var diff = Math.floor((wrap.clientWidth - colModel.getTotalWidth()) / colCount);
for(var i = 0; i < colCount; i++){
colModel.setColumnWidth(i, colModel.getColumnWidth(i) + diff, true);
}
}
this.updateColumns();
},

updateWrapHeight : function(){
var box = this.dropdown.container.getBox(true);
},

render : function(){
var dropdown = this.dropdown;

var dataModel = dropdown.dataModel;
dataModel.onCellUpdated.subscribe(this.updateCell, this, true);
dataModel.onTableDataChanged.subscribe(this.renderRows, this, true);
dataModel.onRowsDeleted.subscribe(this.deleteRows, this, true);
dataModel.onRowsInserted.subscribe(this.insertRows, this, true);
dataModel.onRowsUpdated.subscribe(this.updateRows, this, true);
dataModel.onRowsSorted.subscribe(this.handleSort, this, true);

var colModel = dropdown.colModel;
colModel.onWidthChange.subscribe(this.updateColumns, this, true);
colModel.onHeaderChange.subscribe(this.updateHeaders, this, true);
colModel.onHiddenChange.subscribe(this.handleHiddenChange, this, true);

YAHOO.util.Event.on(window, 'resize', this.adjustForScroll, this, true);
YAHOO.util.Event.on(window, 'resize', this.updateWrapHeight, this, true);

var autoSizeDelegate = this.autoSizeColumn.createDelegate(this);

var colCount = colModel.getColumnCount();

this.cols = [];

if(dropdown.autoSizeColumns){
this.renderRows(dataModel);
this.autoSizeColumns();
}else{
this.updateColumns();
this.renderRows(dataModel);
}

for(var i = 0; i < colCount; i++){
if(colModel.isHidden(i)){
this.hideColumn(i);
}
}
},

updateBodyHeight : function(){
YAHOO.util.Dom.setStyle(this.getBodyTable(), 'height',
(this.dropdown.dataModel.getRowCount()*this.rowHeight)+'px');
}

};

jack.slocum
25 Oct 2006, 4:16 PM
Maybe you could try loading the grid's data and the select's data in a single JSON request and then have the JSON schema point to different points in the data.

Your JSON might look something like this:


{
"grid": [
// grid row data
],
"select": [
// select row data
]
}


Then the grid data model points to "grid" and the select points to "select".

It's a tricky situation since you can't render what isn't there yet.

Rich Kucera
17 Apr 2008, 12:06 PM
You can put a renderer on the column. The renderer could even reference the same select and look up the option. I would recommend closuring it (like below) instead of looking it up every time (expensive).



var myOptions = document.getElementById('my-select').options;
var myRender = function(value){
return myOptions[value].text;
}


Then assign myRender to the column in your column model config with renderer:myRender.


This is really old, but I just used the information :-)



var some_grid = new Ext.grid.EditorGridPanel({
border:false,
ds: some_store,
autoExpandColumn: 'name',


columns: [
{header: "Some ID", width: 120, dataIndex: 'some_id', sortable: true},
{header: "Some Name", width: 180, dataIndex: 'some_name', sortable: true},
{header: "Person Name", width: 180, dataIndex: 'person_name', sortable: true},
{header: "Provider Name", width: 180, dataIndex: 'provider_name', sortable: true},
/*{header: "Status", width: 180, dataIndex: 'ista_id', sortable: true}*/
{
header: "Status",
dataIndex: 'ista_id',
sortable: true,
width: 130,
renderer: function(value){
return statuscode_store.getById(value).data.desc;
},
editor: new Ext.form.ComboBox({
fieldLabel: 'Status',
hiddenName:'status',
store: statuscode_store,
valueField:'code',
displayField:'desc',
...


FWIW