View Full Version : Is there any row renderer
manugoel2003
16 Aug 2007, 6:39 AM
Hi all,
I have a quick question..... is there a way to call a function for every row while rendering?
Regards
Manu Goel
mystix
16 Aug 2007, 8:36 AM
[ moved to Help from General ]
There's something similar.
If you want to apply a style to an entire row, then use:
grid.getView().getRowClass = function(row, index) {
// insert your own code here to determine what style class(es) to add to the row
//mycode
// var val = row.data.value;
// if(val && val.length > 0 && val.charAt(0) == "_") {
// return 'x-unselectable x-layout-panel-hd';
// }
}
Is this what you're looking for?
I just reread your question, and I may have been off in my help (although it still may work...).
If you want to function that is called when each row is rendered, use it and don't return a value.
Otherwise I'd look into GridView.doRender() and maybe firing a custom event or simply a one-liner call to another function.
Hope it helps.
manugoel2003
16 Aug 2007, 11:00 AM
ya, I knew abt that method.... but my requirement is slightly different
actually every row of my grid has a status, and each status has a color associated with it..... so each row needs to be colored according to its status
the list of colors associated with each status is fetched through an AJAX call in the very beginning of the page load..... it is highly dynamic because it is customizable by the user...... that is why I cannot have predefined classes
so I have to color each of the rows either when the entire grid loads by looping through the Ext.select results..... or if there is a way to have a function called after each row render and get a row object in it then it would be gr8
manugoel2003
21 Aug 2007, 5:29 AM
Ok, I would like to ask for your advice
considering my problem, is it better to have a renderer for each column and set the text color like this (color is dynamically fetched every time and stored in config.status object array)
// I have not included the code which calculates "x"
return ("<div style='color: " + config.status[x].color + "'>" + data + "</div>");
or something like this
dataStore.on('load', function(){
var rows = grid.getView().getBodyTable().rows;
for (var x=0; x < rows.length; x++){
var status_id = grid.getAt(x).get("status_id");
for (var y=0; y < config.status.length; y++){
if (config.status[y].id == status_id) {
Ext.select(".x-grid-cell-text", true, rows[x]).each(function(el, scope, index){
el.dom.style.color = config.status[y].color;
});
break;
}
}
}
}, true);
keeping in mind that the grid has around 12 columns and 100 rows on an average..... any help will be appreciated.
Animal
21 Aug 2007, 5:33 AM
http://extjs.com/deploy/ext/docs/output/Ext.grid.GridView.html#getRowClass
My initial concerns are:
How difficult it is to compute 'x', the color to use. If it isn't difficult, then I would go with the renderer.
Also, if modifying the store can affect the color, the renderer will work as expected, whilst the 'initial load' method will retain the original color (unless you add extra code).
My solution would still be:
Using the getRowClass will be called once for each row, as opposed to the renderer which will be called for every cell. It seems as though you could set a style in the getRowClass to set the color for the entire row.
grid.getView().getRowClass = function(row, index) {
var status_id = row.get("status_id");
return 'row_status_' + config.status[status_id].color;
}
.row_status_blue .x-grid-cell-text {
color: blue;
}
.row_status_red .x-grid-cell-text {
color: red;
}
manugoel2003
21 Aug 2007, 6:25 AM
@Animal
I cannot use getRowClass as I cannot set any styles to the row, coz the rows aren't rendered yet.... so I don't have any DOM structure to hook up the style to
@para
I do not know whether the color will be red or green or blue..... it is completely customizable..... so the user could select something like #ff3471 as a color..... so I cannot have predefined classes
So it ends up like this..... we can do only 2 things in the getRowClass method
1. return a class name, which is not possible coz I can't have predefined classes to return
2. modify any part of the existing DOM structure. Which is also not possible as the grid rows aren't rendered yet
even if there was a support for passing inline styles to the row, it wouldn't have worked, as applying "color" to the TR would not affect the TDs
I hope I am able to clarify
That did clarify the problem.
I think that the most robust solution would be to add it to a cell renderer. You just have to make sure to keep the code as simple as possible. I think it will work fine though.
Sorry we couldn't be more help. There just isn't a built in way to do this easier. In this case the best solution would be to modify the GridView's doRender function(s). Add a function call to getRowCellStyle() before it starts generating the markup. Along with one other change, I think it would work...
I would only do this if the cell renderer is way too slow....
No promises on the validity of this code.... :)
doRender : Ext.isGecko ?
function(cs, rs, ds, startRow, colCount, stripe){
var ts = this.templates, ct = ts.cell, rt = ts.row;
// buffers
var buf = "", lbuf = "", cb, lcb, c, p = {}, rp = {}, r, rowIndex;
for(var j = 0, len = rs.length; j < len; j++){
r = rs[j]; cb = ""; lcb = ""; rowIndex = (j+startRow);
var cellStyle = this.getRowCellStyle(r, rowIndex);
for(var i = 0; i < colCount; i++){
c = cs[i];
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.css = p.attr = "";
p.attr += " " + cellStyle;
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
if(p.value == undefined || p.value === "") p.value = " ";
if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
}
var markup = ct.apply(p);
if(!c.locked){
cb+= markup;
}else{
lcb+= markup;
}
}
var alt = [];
if(stripe && ((rowIndex+1) % 2 == 0)){
alt[0] = "x-grid-row-alt";
}
if(r.dirty){
alt[1] = " x-grid-dirty-row";
}
rp.cells = lcb;
if(this.getRowClass){
alt[2] = this.getRowClass(r, rowIndex);
}
rp.alt = alt.join(" ");
lbuf+= rt.apply(rp);
rp.cells = cb;
buf+= rt.apply(rp);
}
return [lbuf, buf];
} :
function(cs, rs, ds, startRow, colCount, stripe){
var ts = this.templates, ct = ts.cell, rt = ts.row;
// buffers
var buf = [], lbuf = [], cb, lcb, c, p = {}, rp = {}, r, rowIndex;
for(var j = 0, len = rs.length; j < len; j++){
r = rs[j]; cb = []; lcb = []; rowIndex = (j+startRow);
var cellStyle = this.getRowCellStyle(r, rowIndex);
for(var i = 0; i < colCount; i++){
c = cs[i];
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.css = p.attr = "";
p.attr += " " + cellStyle;
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
if(p.value == undefined || p.value === "") p.value = " ";
if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
}
var markup = ct.apply(p);
if(!c.locked){
cb[cb.length] = markup;
}else{
lcb[lcb.length] = markup;
}
}
var alt = [];
if(stripe && ((rowIndex+1) % 2 == 0)){
alt[0] = "x-grid-row-alt";
}
if(r.dirty){
alt[1] = " x-grid-dirty-row";
}
rp.cells = lcb;
if(this.getRowClass){
alt[2] = this.getRowClass(r, rowIndex);
}
rp.alt = alt.join(" ");
rp.cells = lcb.join("");
lbuf[lbuf.length] = rt.apply(rp);
rp.cells = cb.join("");
buf[buf.length] = rt.apply(rp);
}
return [lbuf.join(""), buf.join("")];
},
grid.getView().getRowCellStyle = function(row, index) {
var c = '#00ff00'; // or whatever
return 'style="color:' + c + '"';
}
manugoel2003
21 Aug 2007, 8:05 AM
my main concern was not how to simplify the code but to improve performance..... adding 12 renderers which will be called 100 times each is quite expensive, I hope u know what i mean.... but ur code seems to score on both fronts..... thanx for ur code, I'll try it out and then let u know
Thanx for ur help
Manu Goel
manugoel2003
23 Aug 2007, 4:22 AM
@para
I have modified your code as below and it is working like a charm...... the problem was that if you set p.attr inside a renderer then it would override the p.attr set through getRowCellStyle because the renderer was called after the cell style was set..... I just changed their order...... and also added a little exception handling..... thanx for your code
doRender : Ext.isGecko ?
function(cs, rs, ds, startRow, colCount, stripe){
var ts = this.templates, ct = ts.cell, rt = ts.row;
// buffers
var buf = "", lbuf = "", cb, lcb, c, p = {}, rp = {}, r, rowIndex;
for(var j = 0, len = rs.length; j < len; j++){
r = rs[j]; cb = ""; lcb = ""; rowIndex = (j+startRow);
var cellStyle = "";
if (this.getRowCellStyle)
{
cellStyle = this.getRowCellStyle(r, rowIndex);
}
for(var i = 0; i < colCount; i++){
c = cs[i];
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.css = p.attr = "";
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
p.attr += " " + cellStyle;
if(p.value == undefined || p.value === "") p.value = " ";
if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
}
var markup = ct.apply(p);
if(!c.locked){
cb+= markup;
}else{
lcb+= markup;
}
}
var alt = [];
if(stripe && ((rowIndex+1) % 2 == 0)){
alt[0] = "x-grid-row-alt";
}
if(r.dirty){
alt[1] = " x-grid-dirty-row";
}
rp.cells = lcb;
if(this.getRowClass){
alt[2] = this.getRowClass(r, rowIndex);
}
rp.alt = alt.join(" ");
lbuf+= rt.apply(rp);
rp.cells = cb;
buf+= rt.apply(rp);
}
return [lbuf, buf];
} :
function(cs, rs, ds, startRow, colCount, stripe){
var ts = this.templates, ct = ts.cell, rt = ts.row;
// buffers
var buf = [], lbuf = [], cb, lcb, c, p = {}, rp = {}, r, rowIndex;
for(var j = 0, len = rs.length; j < len; j++){
r = rs[j]; cb = []; lcb = []; rowIndex = (j+startRow);
var cellStyle = "";
if (this.getRowCellStyle)
{
cellStyle = this.getRowCellStyle(r, rowIndex);
}
for(var i = 0; i < colCount; i++){
c = cs[i];
p.cellId = "x-grid-cell-" + rowIndex + "-" + i;
p.id = c.id;
p.css = p.attr = "";
p.value = c.renderer(r.data[c.name], p, r, rowIndex, i, ds);
p.attr += " " + cellStyle;
if(p.value == undefined || p.value === "") p.value = " ";
if(r.dirty && typeof r.modified[c.name] !== 'undefined'){
p.css += p.css ? ' x-grid-dirty-cell' : 'x-grid-dirty-cell';
}
var markup = ct.apply(p);
if(!c.locked){
cb[cb.length] = markup;
}else{
lcb[lcb.length] = markup;
}
}
var alt = [];
if(stripe && ((rowIndex+1) % 2 == 0)){
alt[0] = "x-grid-row-alt";
}
if(r.dirty){
alt[1] = " x-grid-dirty-row";
}
rp.cells = lcb;
if(this.getRowClass){
alt[2] = this.getRowClass(r, rowIndex);
}
rp.alt = alt.join(" ");
rp.cells = lcb.join("");
lbuf[lbuf.length] = rt.apply(rp);
rp.cells = cb.join("");
buf[buf.length] = rt.apply(rp);
}
return [lbuf.join(""), buf.join("")];
}
No thx required. I'm merely editing the genius code written by the giants of JS. :)
dantheman
23 Aug 2007, 6:35 AM
How about using CSS.createStyleSheet on the color config you load in the beginning?
Then you could override getRowClass as in the normal case . . .
(since a TR class will cascade to the TD, unless overriden)
Would be a great deal cleaner . . . :D
--dan
manugoel2003
23 Aug 2007, 7:54 AM
I am pathetically bad at that.... do u have any link which I could refer to learn that, in a cross-browser way?.... thanx in advance
dantheman
23 Aug 2007, 9:11 AM
I am pathetically bad at that.... do u have any link which I could refer to learn that, in a cross-browser way?.... thanx in advanceA pseudo-code sketch would be: (I'm rushing to a meeting, so sorry for any typos :) )
Ext.onReady( function(){
// load the color config mapping status -> color, and then create the styles:
var colorStyleSheet = '';
for( var status in colorConfig ) {
// you could put any kind of styles you want here
colorStyleSheet += "status-color-"+status+" { color: "+colorConfig[status]+"; }";
}
Ext.CSS.createStyleSheet( colorStyleSheet );
// then do something Para suggested:
grid.getView().getRowClass = function(row, index) {
var status_id = row.get("status_id");
return 'status-color-' + status_id;
}
});
manugoel2003
23 Aug 2007, 9:37 AM
Oh! I didn't realize it was built into Ext itself..... how stupid of me.... thanx for the effort
Powered by vBulletin® Version 4.1.5 Copyright © 2012 vBulletin Solutions, Inc. All rights reserved.