I can render individual grid columns using a column renderer like this ;
renderer: function(val, meta) {
if (val === 'i') {
meta.style = "background-color:#86b0f4;";
}else if (val === 'n') {
meta.style = "background-color:#fcd1cc;";
}
return val
},
I would like to use this same idea on grid rows.
Unfortunately the only thing I can come across is something along the lines of :
viewConfig: {
getRowClass: function(record, rowIndex, rowParams, store){
return record.get("partytype") == 6 ? "row-highlight" : "";
}
},
This requires me to update the CSS file which I do not want to do.
Can I directly manipulate the css value on a grid row in extjs?
The meta parameter in the column renderer has a record property too. You could lookup the relevant value there instead of relying on the cell value parameter and then add a reference to the same method for each column in the configuration.
Avoiding code duplication, the renderer method could be declared anywhere but to keep this example concise I've just used an IIFE / inline declaration.
{
// Ext.grid.Panel
// ...
columns: (function(){
function columnRenderer(cellValue, meta){
var value = meta.record.get('value');
if(value === 'i')
meta.style = 'background-color:#86b0f4;';
else if(value === 'n')
meta.style = 'background-color:#fcd1cc;';
return cellValue;
}
return [
{
text: 'Foo',
dataIndex: 'foo',
renderer: columnRenderer
},
{
text: 'Bar',
dataIndex: 'bar',
renderer: columnRenderer
}
];
})()
}
ยป Fiddle
Related
TLDR: I'm using ExtJS 4 and I want to change action column buttons icon from hanlder / controller. How I can do it?
My problem: I have a menu to create a group of devices, it cointain a table of all existing devices (the device has an id, name and affiliation to the group member) with pagination and ajax store. To create a group I have to pass an array of device ids to the server.
To do this I add action column to my grid. By clicking on button in action column I want to add device id to one of the two arrays, that are stored as attributes of the grid (addedMembers and deletedMembers) and change icon in action column. At the moment, all the following code works, but I do not understand how I can change the icon?
Grid:
Ext.define('Portal.view.devicegroups.GroupDevicesGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.groupDevicesGrid',
addedMembers: [],
deletedMembers: [],
store: 'devicegroups.GroupDevicesStore',
columns: [
{
dataIndex: 'name',
flex: 1,
sortable: true,
text: Ext.String.capitalize("<?=gettext('name')?>")
},
{
xtype: 'actioncolumn',
text: Ext.String.capitalize("<?=gettext('member')?>"),
width: 75,
items: [
{
getClass: function (value, meta, record, rowIndex, colIndex) {
var cls = 'deny';
if (this.up('groupDevicesGrid').deletedMembers.indexOf(record.get('id')) !== -1 || record.get('member') == 1) {
cls = 'allow';
}
return cls;
},
handler: function (view, rowIndex, colIndex, item, event, record, row) {
this.fireEvent('changeMembership', rowIndex, record);
}
}
]
}
]
});
changeMembership method:
changeGroupDeviceMembership: function(rowIndex, device) {
var groupDevicesGrid = this.getGroupDevicesGrid(),
groupDevicesStore = groupDevicesGrid.getStore(),
addedMembers = groupDevicesGrid.addedMembers,
deletedMembers = groupDevicesGrid.deletedMembers,
deviceId = device.get('id'),
isMember = device.get('member');
if(isMember == 1) {
if(deviceId) {
if(deletedMembers.indexOf(deviceId) === -1) {
// Set allow icon
deletedMembers.push(deviceId);
} else {
// Set deny icon
deletedMembers.splice(deletedMembers.indexOf(deviceId), 1);
}
}
} else if(isMember == 0) {
if(deviceId) {
if(addedMembers.indexOf(deviceId) === -1) {
// Set deny icon
addedMembers.push(deviceId);
} else {
// Set allow icon
addedMembers.splice(deletedMembers.indexOf(deviceId), 1);
}
}
}
},
Or perhaps there is a better solution to my problem?
I am not privileged to comment so I will just take a shot at the answer. This is the way I do it..you are nearly there just add iconCls. :)
{
xtype: 'actioncolumn',
text: Ext.String.capitalize("<?=gettext('member')?>"),
width: 75,
items: [
{
iconCls:'deny', //<== try adding this icon cls
getClass: function (value, meta, record, rowIndex, colIndex) {
var cls = 'deny';
meta.tdAttr = 'data-qtip="Deny"'; //<== I like tool tips
if (this.up('groupDevicesGrid').deletedMembers.indexOf(record.get('id')) !== -1 || record.get('member') == 1) {
cls = 'allow';
meta.tdAttr = 'data-qtip="Allow"'; //<== I like tool tips
}
return cls;
},
handler: function (view, rowIndex, colIndex, item, event, record, row) {
this.fireEvent('changeMembership', rowIndex, record);
}
}
]
}
I use this pattern quite a lot, hopefully it works for you too.
http://2gears.com/2011/05/combobox-editor-remote-and-renderer-for-extjs-editorgridpanel/comment-page-2/#comment-11050?
Please see the function.
I am not using the 'combocolumn' completely. However i have used the major components. Please advise if there is a possibility it should work. As of now the grid refuses to render the column itself and I am unable to pinpoint what the bug is as the code is simply the same?
I did this not to act smart :) - but to simplify and run it on 1 column before standardizing the component common to the project.
The COMBO RENDERING fn()
<code>
function ComboBoxRenderer(combo, gridId) {
var getValue = function (value) {
var idx = combo.store.find(combo.valueField, value);
var rec = combo.store.getAt(idx);
if (rec) {
return rec.get(combo.displayField);
}
return value;
};
return function (value) {
if (combo.store.getCount() === 0 && gridId) {
console.log(combo.store.getCount()+gridId);
combo.store.on(
'load',
function () {
var grid = Ext.getCmp(gridId);
if (grid) {
grid.getView().refresh();
}
},
{
single: true
}
);
return value;
}
return getValue(value);
};
// Ext.getCmp(gridId).getView().refresh();
}
</code>
Editor - in Grid Column Model
{
header: 'Plan Type',
dataIndex: 'plan_id',
editor: {
// allowBlank: 'false',
xtype: 'combobox',
queryMode: 'local',
store: planTypeStore,
displayField: 'plan_name',
valueField: 'plan_id'
}
,renderer: ComboBoxRenderer(this.editor, 'gridPanelId')
/*this is the docs based renderrer - which wont work */
//, renderer: function (val) {
// var rec = planTypeStore.findRecord('plan_id', val);
// return (rec !== null ? rec.get("plan_name") : '');
// }
I have been successfully rendering conditional statement on normal grid column
{
header: ' ',
dataIndex: 'status_b2',
menuDisabled: true,
flex: 1,
sortable: false,
renderer : function(value, meta) {
var status = value.split("<br/>")[0];
if (status == "Unset Price"){
meta.style = "background-color:pink;";
}
else if (status == "Available"){
meta.style = "background-color:green;";
}else if (status == "Booked Unpaid"){
meta.style = "background-color:yellow;";
}else if (status == "Booked Paid"){
meta.style = "background-color:orange;";
}else if (status == "Checked In"){
meta.style = "background-color:red;";
}else if (status == "Checked Out"){
meta.style = "background-color:purple;";
}
return value;
}
My question is how to render with conditional logic on templatecolumn grid? If the room_status == "Dirty", I want to add background-color as red.
{
text: 'Room List',
xtype: 'templatecolumn',
tpl: 'ROOM {room_number} <br/> {room_type_name} <br/> {bed_type} | {room_status}',
menuDisabled: true,
flex: 1,
sortable: false
}
follow these links sencha forum and stackoverflow link
We can have some inline functions and call them. Follow this link. Implement your logic inside these functions.
I too am used to using renderers to add styles to cells to give them highlighting. Effectively, templatecolumn already has a renderer that is applied by default, and it works by basically returning the template applied to the record. So if you want to use your own renderer, you could either replicate the two lines of code from the defaultRenderer, or just call the column's defaultRenderer directly:
function customRenderer(value, metaData, record, rowIndex, colIndex, store, view)
{
if (record.get('severity') == 'critical')
{
metaData.tdCls += ' redHighlight';
}
return view.panel.columns[colIndex].defaultRenderer(value, metaData, record);
};
I try to implement grid with grouping similar to this example:
http://dev.sencha.com/deploy/ext-4.0.0/examples/grid/groupgrid.html
Here data is grouped by column "Cuisine" and sorting by this column sort groups accordingly.
When I paste code of this example into a project, which uses 4.2.1, or in code editor at ExtJS 4.2.1 docs site, the view is exactly the same, sorting works for column "Name", but it doesn't work by column "Cuisine".
Did they remove sorting by grouping column in 4.2.1? If not, how to make it work?
The same example is present in 4.2.1 SDK, and indeed sorting by the grouped column doesn't work anymore. Sounds like a regression to me, you should notify Sencha.
Edit:
That's the code of the method Ext.data.Store#sort that has changed. Restoring the previous version fixes the behaviors (see my comments to find the modified lines):
Ext.define(null, {
override: 'Ext.data.Store'
,sort: function(sorters, direction, where, doSort) {
var me = this,
sorter,
newSorters;
if (Ext.isArray(sorters)) {
doSort = where;
where = direction;
newSorters = sorters;
}
else if (Ext.isObject(sorters)) {
doSort = where;
where = direction;
newSorters = [sorters];
}
else if (Ext.isString(sorters)) {
sorter = me.sorters.get(sorters);
if (!sorter) {
sorter = {
property : sorters,
direction: direction
};
newSorters = [sorter];
}
else if (direction === undefined) {
sorter.toggle();
}
else {
sorter.setDirection(direction);
}
}
if (newSorters && newSorters.length) {
newSorters = me.decodeSorters(newSorters);
if (Ext.isString(where)) {
if (where === 'prepend') {
// <code from 4.2.1>
// me.sorters.insert(0, newSorters);
// </code from 4.2.1>
// <code from 4.2.0>
sorters = me.sorters.clone().items;
me.sorters.clear();
me.sorters.addAll(newSorters);
me.sorters.addAll(sorters);
// </code from 4.2.0>
}
else {
me.sorters.addAll(newSorters);
}
}
else {
me.sorters.clear();
me.sorters.addAll(newSorters);
}
}
if (doSort !== false) {
me.fireEvent('beforesort', me, newSorters);
me.onBeforeSort(newSorters);
sorters = me.sorters.items;
if (sorters.length) {
me.doSort(me.generateComparator());
}
}
}
});
set sortable: true either on a defaults config for the grouping column or as a config on the child columns themselves. e.g.
{
// NOTE: these two are grouped columns
text: 'Close',
columns: [{
text: 'Value',
minWidth: 100,
flex: 100,
sortable: true,
dataIndex: 'ValueHeld_End'
}, {
text: 'Total',
minWidth: 110,
flex: 110,
sortable: true,
dataIndex: 'TotalPnL'
}]
}
In an ExtJS GridPanel, is there a way to design a column whose sole purpose is to act as a serial number column? This column will not need a dataIndex property.
Right now, I am using a custom row numberer function, but this means the row numberer is defined in the grid.js file and all columns from grid.ui.js needs to be copied into grid.js.
I am using the Ext designer.
EDIT: The crux of my question is: Is there a way to define a row numberer using the Ext designer?
All you need is an Ext.grid.RowNumberer in your column definition.
var colModel = new Ext.grid.ColumnModel([
new Ext.grid.RowNumberer(),
{header: "Name", width: 80, sortable: true},
{header: "Code", width: 50, sortable: true},
{header: "Description", width: 200, sortable: true}
]);
Not an answer, but just want to share this:-
On top of the Ext.grid.RowNumberer, you can have this small nifty hack which will increments your numbers correctly according to the page number that you are viewing if you have implemented PagingToolbar in your grid.
Below is my working example. I extended the original Ext.grid.RowNumberer to avoid confliction.
Kore.ux.grid.RowNumberer = Ext.extend(Ext.grid.RowNumberer, {
renderer: function(v, p, record, rowIndex) {
if (this.rowspan) {
p.cellAttr = 'rowspan="'+this.rowspan+'"';
}
var st = record.store;
if (st.lastOptions.params && st.lastOptions.params.start != undefined && st.lastOptions.params.limit != undefined) {
var page = Math.floor(st.lastOptions.params.start/st.lastOptions.params.limit);
var limit = st.lastOptions.params.limit;
return limit*page + rowIndex+1;
}else{
return rowIndex+1;
}
}
});
And the code below is the original renderer from Ext.grid.RowNumberer, which, to me, pretty ugly because the numbers is fixed all the time no matter what page number it is.
renderer : function(v, p, record, rowIndex){
if(this.rowspan){
p.cellAttr = 'rowspan="'+this.rowspan+'"';
}
return rowIndex+1;
}
For version 4.2 very very easy:
Just add a new column like this:
{
xtype: 'rownumberer',
width: 40,
sortable: false,
locked: true
}
ExtJS 4.2.1 working code below:
// Row numberer correct increasing
Ext.override(Ext.grid.RowNumberer, {
renderer: function(v, p, record, rowIndex) {
if (this.rowspan) {
p.cellAttr = 'rowspan="'+this.rowspan+'"';
}
var st = record.store;
if (st.lastOptions.page != undefined && st.lastOptions.start != undefined && st.lastOptions.limit != undefined) {
var page = st.lastOptions.page - 1;
var limit = st.lastOptions.limit;
return limit*page + rowIndex+1;
} else {
return rowIndex+1;
}
}
});