PDA

View Full Version : Need custom renderer for progress bar in grid cell, to read 2 values & output to bar



pwelby
22 Nov 2010, 9:11 AM
I need a custom renderer to read from two different fields from a JsonStore and output to a Progress Bar in a GridPanel cell. The values I am reading from the Json output are strings, so I am converting them to INT in the field config for the store in order to output to the progress bar - this works but is very crude and not what I ideally want. For the renderer to function as it should it needs to run in the ColumnModel, but I am not able to get this working. What I need is a custom renderer to read from the field values I want and then output to the particular progress bar in the Grid cell I want the value to show in.



I found this article by Cutter Blades:

My First ExtJS DataGrid Pt 7: Custom Cell Renderers
Posted At : August 22, 2007 9:07 AM | Posted By : Cutter
Related Categories: My First ExtJS DataGrid, ExtJS, Development, JQuery

So, it's been awhile. No, I haven't forgotten you, I've just been busy with a lot of things. One of which has been implementing a new ExtJS DataGrid in a project I'm working on. Sure, there's a lot more going on, but that's becoming a nice front end piece. As previously promised, I want to look at a renderer.

What Is A Renderer?
Hey, not everything you get back from your paging query will be formatted in the way you want it displayed. I'm going to show you a really simple example, dealing with a boolean value. Let's start off by writing a renderer function. Here's the deal, you have a query column with a boolean value (bIsActive), which is returned as either 1 or 0. You want the grid to display Yes or No. You could define the function directly in your ColumnModel declaration:
...
,{
header:'Active',
dataIndex:'bIsActive',
renderer:function(value){
return (value == 1)?'Yes':'No';}
}
...
Easy, right? But, it's not really reusable is it? So, it's better to define the function, then register that function as the renderer for the column. Now, there isn't a ton of documentation on exactly what's going on here, but there are a lot of examples, so I'll try to give you what I've figured out, plus what I believe to be right (if you know it better then let us all know).

A renderer function will take at least one argument by default, that being the value of the cell being rendered. You do not explicitly call a renderer, the arguments passed to the renderer are dependent upon the function definition. For something as simple as a Yes/No boolean renderer the value is all that's necessary. So you would define a renderer function, and register it, like this:

function renderBoolean(value){
return String.format("{0}",(value==1)?'Yes':'No');
}

// And a redefinition of of the renderer in the ColumnModel
...
,{
header:'Active',
dataIndex:'bIsActive',
renderer:renderBoolean
}
...
Did you see it? No parens on the end of that renderer config property in the ColumnModel, and no arguments explicitly passed. That's all covered by the ExtJS framework. But wait, it gets better. We had two columns in the data store that relate to a person's name (vcFirstName and vcLastName). What if we just wanted to concantenate the two values? Well for that we would probably need the entire record. No problem, you just change things up a bit:

function renderName(value,p,r){
return String.format("{0} {1}", value, r.data['vcLastName']);
}
// Combine our 'name' columns into one
...
,{
header:'Name',
dataIndex:'vcFirstName',
renderer:renderName
}
...
OK, three arguments, with one never used. Well, it wasn't used in this case, but it's necessary, as you can't get the third argument (the data record) passed into the renderer without also passing in the second argument. What's the second argument? Well, that's a great question. I'm fairly sure that it is the element object of the container of the value, but I could be very wrong. In this particular case it doesn't matter, but I'll give you another item renderer in a future post where it will play a part.

You'll also want to note the the JavaScript bind variable syntax being used in the String.format() function, {[value]}. The numbers used here are like array position values, starting at zero, for all of the variables passed in the arguments that follow the string you are formatting (the first argument of the function).
..........................




This article shows some idea close to what I want, but I am not seeing how I can do it though. Above, Cutter is basically saying that one can read from two field inputs and output to one cell. This is what I want to do similarly. I want to be able to read from two field values and if one is 'Y' to output an INTEGER VALUE to the progress bar for the cell for that set of values.

Problem is if I try to run the code as he has, with the renderer in the ColumnModel then I am only outputting a string value to the cell, and it is not rendering in the progress bar.

...and if I try to create a function to do the work and call it as 'renderer:' in the ColumnModel instead of running the anonymous function in the field config, it won't run either

I want to have 4 progress bars - one for each phase, and I am reading at least 2 fields for each progress bar in the Grid cell. The value will either be a message of 'Y' or an error of 'Y' if it is an error then I need to render the progress bar as a 'RED' color with an INT, for that phase, if not then I need to render the progress bar as 'GREEN' showing the INT for progress for that phase.

If you look at the field values I have for example - "IS_SYNCFILE_WRITTEN", if this message comes back as 'Y' then I will output a GREEN progress bar showing 100%. IF this value is 'N' then I will need to look at "IS_SYNCFILE_ERROR". If this is 'Y' then I need to put a RED progress bar showing 100% and then I need to read a third field - "STATUS" to get the actual error message and output that message above the progress bar or below it, or in another field called ERROR of something.


I am attaching my code snippet to see this:



// functions
function renderSyncfile(value, meta, record) {
var ISW = record.data.IS_SYNCFILE_WRITTEN;
var ISE = record.data.IS_SYNCFILE_ERROR;
if (ISW === 'Y') {
ISW.value = 100;
}
else if (ISE === 'Y') {
ISW.value = 25;
}
else ISW.value = 0;
return ISW.value;
}

function renderBoolean(value){
return String.format("{0}",(value=='Y')? 100: 0);
}

function output100(value) {
return value === 'Y' ? 100 : 0;
}

/**********************************/

// custom plugin Ext.ux.grid.plugin.ProgressColumn
var statusColumn_p1 = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "Sync files",
dataIndex : 'IS_SYNCFILE_WRITTEN',
//renderer: output100,
/* renderer: function(value, meta, record) {
var ISW = record.data.IS_SYNCFILE_WRITTEN;
var ISE = record.data.IS_SYNCFILE_ERROR;
if (ISW == 'Y') {
return value = 100;
}
else if (ISE == 'Y') {
return value = 25;
}
else
return 0;

},
*/ width : 40,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'Syncfiles written', // string added below the bar (defaults to null)
textPst : '%', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusColumn_p2a = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "UFS start",
dataIndex : 'UFS_START_DATE',
width : 40,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'UFS start date', // string added below the bar (defaults to null)
textPst : '%', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusColumn_p2b = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "UFS",
dataIndex : 'UFS_END_DATE',
width : 40,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'UFS end date', // string added below the bar (defaults to null)
textPst : '%', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusColumn_p3 = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "User files",
dataIndex : 'IS_USERFILE_WRITTEN',
width : 40,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'Userfiles written', // string added below the bar (defaults to null)
textPst : '%', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusErrorColumn_p3 = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "Error",
dataIndex : 'IS_USERFILE_ERROR',
width : 30,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'Userfiles written', // string added below the bar (defaults to null)
textPst : '', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});


var statusColumn_p4a = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "Build start",
dataIndex : 'BUILD_START_DATE',
width : 40,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'Build start date', // string added below the bar (defaults to null)
textPst : '%', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusColumn_p4b = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "Build end",
dataIndex : 'BUILD_END_DATE',
width : 40,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'Build end date', // string added below the bar (defaults to null)
textPst : '%', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusColumn_p4c = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "Build",
dataIndex : 'IS_BUILD_FINISHED',
width : 40,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'Build complete', // string added below the bar (defaults to null)
textPst : '%', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusErrorColumn_p4 = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "Error",
dataIndex : 'IS_ERROR',
width : 30,
//invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 200, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'Build complete', // string added below the bar (defaults to null)
textPst : '', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});

var statusErrorColumn = new Ext.ComponentMgr.createPlugin({
ptype: 'progresscolumn',
header : "Error",
dataIndex : 'IS_ERROR',
width : 20,
invertedColor: true, // inverts the color when colored: true (defaults to false)
//ceiling: 100, // integer for when your max value is not 100 (defaults to 100)
//topText: 'testing 1.2.3', // string added above the bar (defaults to null)
//bottomText: 'An Error', // string added below the bar (defaults to null)
textPst : '', // string added to the end of the cell value (defaults to '%')
//colored : false, // True for pretty colors, false for just blue (defaults to true)
editor : new Ext.form.TextField() // Define an editor if you want to edit
});


function convertStringToInt(value){
return function(value){
return value === 'Y' ? 100 : 0;
}
//return String.format("{0}",(value=='Y')? 100 : 0 );
}

function renderErrorWithMsg(value,p,r){
return String.format("{0} {1}", value, r.data['IS_ERROR']);
}

function formatSyncfileWrittenAndError(val, x, store){
if (store.data.IS_SYNCFILE_WRITTEN.value == 'Y') {
return value == 'Y' ? 100 : 0;
}
else if (store.data.IS_SYNCFILE_ERROR.value == 'Y') {
return value == 'Y' ? 25 : 0;
}
//return store.data.IS_SYNCFILE_WRITTEN + ' ' + val + ', ' + store.data.IS_SYNCFILE_ERROR ;
//}

//renderer: function(val, meta, record) {
//var userId = record.data.user_id;

}

//build Host store
var hostListStore = new Ext.data.JsonStore({

root : 'message',
proxy: new Ext.data.HttpProxy({
// Call web service method using GET syntax
url : 'application/models/build/host/list_svc.php',
// Ask for Json response
headers: { 'Content-type': 'application/json' },
method: "GET"
}),
remoteSort: true,
fields : [
{ name: 'ID', type: 'int'},

{ name: 'BUILD_ID'},
{ name: 'HOST'},
{ name: 'USERNAME'},
'P4_SERVER',
'P4_TICKET',
'CSPEC_NAME',
'CSPEC_ROOT',
'PLF_NAME',
'BUILD_PATH',
'BUILD_COMMAND',
'BUILD_MODE',

// phase 1
{ name: 'IS_SYNCFILE_WRITTEN',
convert: function(value){
return value === 'Y' ? 100 : 0;
}
},
{ name: 'IS_SYNCFILE_ERROR',
convert: function(value){
return value === 'Y' ? 25 : 0;
}
},

// phase 2
{ name: 'UFS_START_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'UFS_END_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'IS_UFS_ERROR',
convert: function(value){
return value === 'Y' ? 25 : 0;
}
},

// phase 3
{ name: 'IS_USERFILE_WRITTEN',
convert: function(value){
return value === 'Y' ? 100 : 0;
}
},
{ name: 'IS_USERFILE_ERROR',
convert: function(value){
return value === 'Y' ? 25 : 0;
}
},

// phase 4
{ name: 'BUILD_START_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'BUILD_END_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'IS_BUILD_FINISHED',
convert: function(value){
return value === 'Y' ? 100 : 0;
}
},
{ name: 'IS_ERROR',
convert: function(value){
if (value === 'Y') {
return value === 'Y' ? 100 : 0;
}
}
},

{ name: 'STATUS', width: 150}
]
});

//Users listing
var userListStore = new Ext.data.JsonStore({
root : 'message',
proxy: new Ext.data.HttpProxy({
// Call web service method using GET syntax
url : 'application/models/build/my/list_svc.php',
// Ask for Json response
headers: { 'Content-type': 'application/json' },
method: "GET"
}),
fields : [
{ name: 'ID', type: 'int'},

{ name: 'BUILD_ID'},
{ name: 'HOST'},
{ name: 'USERNAME'},
'P4_SERVER',
'P4_TICKET',
'CSPEC_NAME',
'CSPEC_ROOT',
'PLF_NAME',
'BUILD_PATH',
'BUILD_COMMAND',
'BUILD_MODE',

// phase 1
{ name: 'IS_SYNCFILE_WRITTEN',
convert: function(value){
return value === 'Y' ? 100 : 0;
}
},
{ name: 'IS_SYNCFILE_ERROR',
convert: function(value){
return value === 'Y' ? 25 : 0;
}
},

// phase 2
{ name: 'UFS_START_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'UFS_END_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'IS_UFS_ERROR',
convert: function(value){
return value === 'Y' ? 25 : 0;
}
},

// phase 3
{ name: 'IS_USERFILE_WRITTEN',
convert: function(value){
return value === 'Y' ? 100 : 0;
}
},
{ name: 'IS_USERFILE_ERROR',
convert: function(value){
return value === 'Y' ? 25 : 0;
}
},

// phase 4
{ name: 'BUILD_START_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'BUILD_END_DATE',
convert: function(value){
return value !== null ? 100 : 0;
}
},
{ name: 'IS_BUILD_FINISHED',
convert: function(value){
return value === 'Y' ? 100 : 0;
}
},
{ name: 'IS_ERROR',
convert: function(value){
if (value === 'Y') {
return value === 'Y' ? 100 : 0;
}
}
},

{ name: 'STATUS', width: 150}
]
});

// HostList column model
var hostListColumnModel = new Ext.grid.ColumnModel([
{header : "Username", dataIndex: 'USERNAME', width: 50},
{header : "Build ID", dataIndex: 'BUILD_ID', width: 30},
statusColumn_p1, statusColumn_p2b, statusColumn_p3, statusColumn_p4c, statusErrorColumn,
{header : "Status", dataIndex: 'STATUS'},
rerunBuildProcess

]);

// UserList column model
var userListColumnModel = new Ext.grid.ColumnModel([
{header : "Username", dataIndex: 'USERNAME', width: 50},
{header : "Build ID", dataIndex: 'BUILD_ID', width: 30},
statusColumn_p1, statusColumn_p2b, statusColumn_p3, statusColumn_p4c, statusErrorColumn,
{header : "Status", dataIndex: 'STATUS'},
rerunBuildProcess
]);



and here is the Grid I am rendering the bar into:



//Build Host listing
var theGrid = new Ext.grid.GridPanel({
title : 'Hosts and User builds',
store : hostListStore,
autoScroll : true,
loadMask : true,
method : 'GET',
layout : 'fit',
height : 600,
plugins : [ statusColumn_p1, statusColumn_p2b, statusColumn_p3, statusColumn_p4c, statusErrorColumn ],
overflow : scroll,
cm : hostListColumnModel,
selModel : rerunBuildProcess,
//sm : new Ext.grid.RowSelectionModel({ singleSelect: true }),
clicksToEdit : 1,
tbar: [{
xtype : 'combo',
store: new Ext.data.ArrayStore({
id: 0,
fields: [
'myId',
'displayText'
],
data: [[1,'qsd8650-lab9'], [2,'qsd8650-lab10'], [3,'qsd8650-lab11']]
}),
text : 'Host',
valueField : 'myId',
displayField : 'displayText',
typeAhead : true,
triggerAction : 'all',
lazyRender : true,
anchor : '100%',
mode : 'local',
emptyText : 'Select a Host...',
listeners : {
'select' : {
scope : this,
fn : function (combo, record) {

// get vars
var selectedHost = record.get('displayText');
top.selectedHost = selectedHost;

// Change the title to Hosts Listing
theGrid.setTitle('Listing for Host: \'' + selectedHost + '\'');

//call getStatus timer
clearTimeout(myTimer);
getBuildHostStatus.init(selectedHost);


}
} // eo 'select'
} // eo listeners

},'-',{
xtype : 'button',
text : 'My Builds',
style : 'padding: 0px 10px 0px 0px',
id : 'myBuildsListingBtn',
handler : function() {

////Change the title to - My Listing
theGrid.setTitle('My builds listing');

// call getStatus timer
clearTimeout(hostTimer);
getBuildMyStatus.init();

}
},{
xtype : 'tbfill'
}],
viewConfig: {
forceFit: true
}
});

Condor
23 Nov 2010, 7:01 AM
A renderer should return HTML.

In case of a progress bar you probably want to return:

<div style="width: <x>; background-color: <y>">&#160;</div>'

pwelby
23 Nov 2010, 8:22 AM
This has got me totally confused. I need the renderer to return the response I need to show in the progress bar. Changing color and changing the value that the bar reads. I can get a bar to output if I use one bar for each field response, but I am not getting it to read for each 'phase' I have set up. Ideally I want 1(one) progress bar to show the progress as a percentage, and if there is an error to have the error show either on top of, or under or even over the bar, and have the bar turn 'red'.

If I was to have one progress bar and have it read all the response coming through from the fields and then convert them to INT for the progress bar to output, how do I then change the color to red if there is an error passed during the reading of the phases? the messages that are coming in ar eto be read in a sequence as well. so that - SYNCFILES are read first, then UFS, then USERFILES then BUILD.