I have conditional styling on grid rows, styling works initially but it does not respond to data change. Lets say if you edit a column to be a minus value lets say then I want its style change back to red.
I tried
grid.doLayout();
grid.doComponentLayout();
grid.update();
grid.updateLayout()
so how I can enforce grid to update the css on the row (how do I trigger getRowClass, or is there any other way of doing this).
What you are trying to do will only be possible if you run reconfigure with the same columnmodel on the grid. override the getRowClass property of the view cause the grid.Panel itself has none.
gridReference.getView().getRowClass = function(record, rowIndex, rowParams, store){
// your code
}
See the JSFiddle example for this
Alternatively you may use the renderer
Use the renderer but this time you change the meta data of the cell by adding a class. This can be done by modifing the second param of the renderer which is a meta-object like so:
var classRenderer = function(v,m) {
if (v=='Lisa') {
m.tdCls = 'demo'
}
return v;
}
here'S a JSFiddle in addition
You can use the renderer config for the column...
function change(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '</span>';
}
return val;
}
function pctChange(val) {
if (val > 0) {
return '<span style="color:green;">' + val + '%</span>';
} else if (val < 0) {
return '<span style="color:red;">' + val + '%</span>';
}
return val;
}
// create the Grid
var grid = Ext.create('Ext.grid.Panel', {
store: store,
stateful: true,
collapsible: true,
multiSelect: true,
stateId: 'stateGrid',
columns: [
{
text : 'Company',
flex : 1,
sortable : false,
dataIndex: 'company'
},
{
text : 'Price',
width : 75,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price'
},
{
text : 'Change',
width : 75,
sortable : true,
renderer : change,
dataIndex: 'change'
},
{
text : '% Change',
width : 75,
sortable : true,
renderer : pctChange,
dataIndex: 'pctChange'
},
{
text : 'Last Updated',
width : 85,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}
],
height: 350,
width: 600,
title: 'Array Grid',
renderTo: 'grid-example',
viewConfig: {
stripeRows: true,
enableTextSelection: true
}
});
Related
I'm creating grid as follows. I want to change the style of the row depending on a condition
Also, the date column should have value in format -> 'd.m.Y'. If condition gets true, I want to change the color of the row. But because date column has its own renderer method, the default renderer doesn't work.
How can we run both the renderer methods?
columns : {
defaults : {
renderer : function(value, meta, record) {
if (record.get('status') === false) {
meta.style = "color:#FF0000;";
}
return value;
}
},
items : [ {
text : 'Number',
dataIndex : 'number',
flex : 1
}, {
text : 'Type'),
dataIndex : 'type',
flex : 1
}, {
text : 'Date',
dataIndex : 'date',
renderer : Ext.util.Format.dateRenderer('d.m.Y'),
flex : 1
}]
}
The default renderer is only called when you don't have a renderer in a column, you can just make a renderer in the date column that format the date and applies the meta style as well.
columns: {
defaults: {
renderer: function(value, meta, record) {
if (record.get('status') === false) {
meta.style = "color:#FF0000;";
}
return value;
}
},
items: [{
text: 'Number',
dataIndex: 'number',
flex: 1
}, {
text: 'Type',
dataIndex: 'type',
flex: 1
},
{
text: 'Date',
dataIndex: 'date',
renderer: function(value, meta, record) {
if (record.get('status') === false) {
meta.style = "color:#FF0000;";
}
return Ext.Date.format(value, 'd.m.Y');
},
flex: 1
}]
}
Using renderer function from controller
Ext.define('Fiddle.view.GridController', {
extend: 'Ext.app.ViewController',
alias: 'controller.gridcontroller',
dateRenderer: function (value, meta, record) {
if(record.get('status') === false) {
meta.style = "color:#FF0000;";
}
return Ext.Date.format(value, 'd.m.Y');
},
})
Ext.create('Ext.grid.Panel', {
controller: 'gridcontroller',
columns:
//other properties...
{
text: 'Date',
dataIndex: 'date',
renderer: 'dateRenderer',
flex: 1
}
//other properties...
})
Fiddle here
I have already tried grid.getColumnModel().getColumnHeader(columnIndex); but this doesn't work. I am using a custom grid selection model.I want to get column header value whenever any cell in corresponding column is clicked
You need to add cellClick listener to the panel, here is the modified code
var grid1 = Ext.create('Ext.grid.Panel', {
renderTo: Ext.getBody(),
store: store,
width:0.3*Ext.getBody().getViewSize().width,
height: 0.5*Ext.getBody().getViewSize().height,
columnLines: true,
columns: [{
text : 'Company',
locked : true,
sortable : false,
dataIndex: 'company',
renderer : function (value, metaData, record, row, col, store,gridView) {
metaData.tdAttr = 'data-qtip="' + value + '"';
return value;
}
},{
text : 'Price',
width : 125,
locked:true,
sortable : true,
renderer : 'usMoney',
dataIndex: 'price',
},{
text : 'Change',
width : 555,
sortable : true,
dataIndex: 'change',
renderer : function (value, metaData, record, row, col, store, gridView) {
metaData.tdAttr = 'data-qtip="' + value + '"';
return value;
}
},{
text : '% Change',
width : 555,
sortable : true,
renderer : pctChange,
dataIndex: 'pctChange',
},{
text : 'Last Updated',
width : 555,
sortable : true,
renderer : Ext.util.Format.dateRenderer('m/d/Y'),
dataIndex: 'lastChange'
}],
title: 'Locking Grid Column',
selType: 'cellmodel',
selModel: Ext.create('MyApp.MultiCellSelectionModel',{
mode: 'MULTI',
allowDeselect: true
}),
multiSelect: true,
listeners : {
cellclick( grid, cell, columnIndex, record , node , rowIndex , evt){
var cellId = grid.getHeaderCt().getHeaderAtIndex(columnIndex).id;
var dataIndex = grid.getHeaderCt().getHeaderAtIndex(columnIndex).dataIndex;
var text = grid.getHeaderCt().getHeaderAtIndex(columnIndex).text;
alert(dataIndex);
alert(text);
}
}
});
I have an ExtJs EditorGridPanel with a custom renderer. The basic idea is to display a checkbox when an item needs to be registered and the text Registered when an item is already registered. Everything is working swimmingly except for when clicking on the header, the entire grid re-renders and every cell toggles. Furthermore, the sort does not work. How to I tell when the header has been clicked so that all my checkboxes do not toggle? How do I fix the sort for the column? Right now it does not sort. Thanks in advance for your help.
var colModel = new Ext.grid.ColumnModel(
{
columns: [
{ id: 'ItemOid', header: "ItemOid", width: 100, sortable: true, locked: true, dataIndex: 'ItemOid', hidden: true },
{ id: 'nNumber', header: "N-#", width: 100, sortable: true, locked: true, dataIndex: 'NNumber' },
{ header: "Make", width: 150, sortable: true, dataIndex: 'Make' },
{ header: "Model", width: 150, sortable: true, dataIndex: 'Model' },
{ header: "Register",
width: 55,
sortable: true,
dataIndex: 'Register',
xtype: 'checkcolumn',
renderer: renderFunction
}
]
});
function renderFunction(value, metaData, record, rowIndex, colIndex, store) {
if (!store.getAt(rowIndex).data['ItemNeedsRegistered'])
return 'Registered';
var isRegistered = store.getAt(rowIndex).data['Registered'];
var renderString;
if (initialItemRender || isRegistered) {
renderString = '<input type="checkbox" id="chkRegistered' + rowIndex + '" />';
store.getAt(rowIndex).data['Registered'] = false;
} else {
renderString = '<input type="checkbox" checked="yes" id="chkRegistered' + rowIndex + '" />';
store.getAt(rowIndex).data['Registered'] = true;
}
return renderString;
}
var grid = new Ext.grid.EditorGridPanel({
store: itemStore,
cm: colModel,
sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),
viewConfig: {
forceFit: true
},
height: 100,
split: true,
region: 'north'
});
Here is my second attempt that also fails, by trying to update the underlying value and it does not check or uncheck.
function renderFunction(value, metaData, record, rowIndex, colIndex, store) {
if (!store.getAt(rowIndex).data['ItemNeedsRegistered'])
return 'Registered';
var isRegistered = store.getAt(rowIndex).data['Registered'];
var renderString;
if (initialItemRender || !isRegistered) {
renderString = '<input type="checkbox" id="chkRegistered' + rowIndex + '"'
+ ' onClick="updateStoreOnClick(' + rowIndex + ', true);"'
+ ' />';
} else {
renderString = '<input type="checkbox" checked="yes" id="chkRegistered' + rowIndex + '"'
+ ' onClick="updateStoreOnClick(' + rowIndex + ', false);"'
+ ' />';
}
return renderString;
}
function updateStoreOnClick(rowIndex, value) {
store.getAt(rowIndex).data['Registered'] = value;
}
The toggling problem is occurring because you're directly updating each record's Registered attribute during the render. The next time you cause a render of the grid (e.g., when sorting), the values of all the records' Registered attributes are the boolean opposite of what they were to begin with. You probably shouldn't be changing those attributes during render, but instead find a way to get the correct value from the checkbox just before saving.
For sorting, you can manually create a numeric attribute on your record that contains a semi-arbitrary value specifically for sorting. For example, call the attribute RegisteredSort and give it these values:
1 — items not requiring registration
2 — registered items
3 — unregistered items
Then you use the RegisteredSort attribute as the dataIndex for that column rather than Registered.
I believe the rowIndex will be 0 when you click on the header... How about adding
if(rowIndex == 0) return;
to the top of renderFunction?
I ended up doing a custom check column:
//#region Custom Check Column
AVRMS.AircraftRegisterCheckColumn = Ext.extend(Ext.grid.Column, {
/**
* #private
* Process and refire events routed from the GridView's processEvent method.
*/
processEvent: function(name, e, grid, rowIndex, colIndex) {
if (name == 'mousedown') {
var record = grid.store.getAt(rowIndex);
if (grid.store.getAt(rowIndex).data['AircraftNeedsRegistered'])
record.set(this.dataIndex, !record.data[this.dataIndex]);
return false; // Cancel row selection.
} else {
return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
}
},
renderer: function(v, p, rec, rowIndex, colIndex, store) {
if (!store.getAt(rowIndex).data['AircraftNeedsRegistered'])
return store.getAt(rowIndex).data['Status'];
p.css += ' x-grid3-check-col-td';
return String.format('<div class="x-grid3-check-col{0}"> </div>', v ? '-on' : '');
},
// Deprecate use as a plugin. Remove in 4.0
init: Ext.emptyFn
});
Ext.reg('airRegChkCol', AVRMS.AircraftRegisterCheckColumn);
// register ptype. Deprecate. Remove in 4.0
Ext.preg('airRegChkCol', AVRMS.AircraftRegisterCheckColumn);
// register Column xtype
Ext.grid.Column.types.airRegChkCol = AVRMS.AircraftRegisterCheckColumn;
//#endregion
//#region ColumnModel
var colModel = new Ext.grid.ColumnModel(
{
columns: [
{ id: 'AircraftOid', header: "AircraftOid", width: 100, sortable: true, locked: true, hideable: false, dataIndex: 'AircraftOid', hidden: true, menuDisabled: true },
{ id: 'nNumber', header: "N-Number", width: 75, sortable: true, locked: true, hideable: false, dataIndex: 'NNumber', menuDisabled: true },
{ header: "Make", width: 150, sortable: true, hideable: false, dataIndex: 'Make', menuDisabled: true },
{ header: "Model", width: 150, sortable: true, hideable: false, dataIndex: 'Model', menuDisabled: true },
{
header: "Airworthy",
width: 75,
sortable: true,
hideable: false,
dataIndex: 'Airworthy',
menuDisabled: true,
renderer: function (value, metaData, record, rowIndex, colIndex, store) {
if (value == true)
return 'Yes';
return 'No';
},
editor: new Ext.form.ComboBox({
id: 'makeCombo',
typeAhead: true,
store: airworthy,
triggerAction: 'all',
forceSelection: true,
mode: 'local',
allowBlank: false,
selectOnFocus: true,
lazyRender: true,
listClass: 'x-combo-list-small'
})
},
{
id: 'Register',
header: "Select to Register",
width: 75,
sortable: true,
dataIndex: 'Register',
xtype: 'airRegChkCol',
hideable: false,
menuDisabled: true
}]
});
//#endregion
//#region grid
var grid = new Ext.grid.EditorGridPanel({
store: aircraftStore,
cm: colModel,
sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),
viewConfig: {
forceFit: true
},
height: 100,
split: true,
region: 'north'
});
//#endregion
I am using ExtJs 3.4. I have a checkbox control in an ExtJs Grid. I want to disable the checkbox control based on when a value in the store is equal to zero.
I have tried this and it does not disable it:
var colModel = new Ext.grid.ColumnModel(
{
columns: [
{ id: 'AircraftOid', header: "AircraftOid", width: 100, sortable: true, locked: true, dataIndex: 'AircraftOid', hidden: true },
{ id: 'nNumber', header: "N-#", width: 100, sortable: true, locked: true, dataIndex: 'NNumber' },
{ header: "Make", width: 150, sortable: true, dataIndex: 'Make' },
{ header: "Model", width: 150, sortable: true, dataIndex: 'Model' },
{ header: "Register",
width: 55,
sortable: true,
dataIndex: 'Register',
xtype: 'checkcolumn'
}
],
isCellEditable: function (col, row) {
return false;
}
});
var grid = new Ext.grid.GridPanel({
store: aircraftStore,
cm: colModel,
sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),
viewConfig: {
forceFit: true
},
height: 100,
split: true,
region: 'north'
});
Thanks in advance.
Your thought was right. But...
First, you're overriding column model's isCellEditable method to prevent editing. But Grid doesn't calls that method. It only works on EditorGrid.
Second, Ext.ux.grid.CheckColumn doesn't handle any editable features, because it's not an editor, it's just a column.
So for my project i modified it to act as a editor and added the readOnly property to prevent editing on normal Grids. If you set readOnly to true, it'll not be clickable anymore.
Ext.ux.grid.CheckColumn = Ext.extend(Ext.grid.Column, {
processEvent : function(name, e, grid, rowIndex, colIndex) {
if ( !this.readOnly && name == 'mousedown' ) {
grid.stopEditing();
var record = grid.store.getAt(rowIndex);
var cm = grid.getColumnModel();
var edit_e = {
grid: grid,
record: record,
field: this.dataIndex,
value: record.data[this.dataIndex],
row: rowIndex,
column: colIndex,
cancel: false
};
if ( grid.fireEvent( 'beforeedit', edit_e ) !== false && !edit_e.cancel ) {
record.set( this.dataIndex, !record.data[this.dataIndex] );
edit_e.cancel = null;
grid.fireEvent( 'afteredit', edit_e );
}
return false;
} else {
return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
}
},
editable : false,
readOnly : false,
renderer : function(v, p, record){
p.css += ' x-grid3-check-col-td';
return String.format('<div class="x-grid3-check-col{0}"> </div>', v ? '-on' : '');
},
init: Ext.emptyFn
});
Ext.preg('checkcolumn', Ext.ux.grid.CheckColumn);
Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn;
Ext.grid.Column.types.checkcolumn = Ext.ux.grid.CheckColumn;
I dont understand how to create two date columns and create range between them?
For example I have Grid where is some column (deadline date), and i have 2 datefields, where I can write: From what day and Till what day .
How then I can filter data between those days that I choosed?
**SOME CODE:**
// create the Grid
var grid = new Ext.grid.GridPanel({
store : store,
id : 'grid',
columns : [
new Ext.grid.RowNumberer({width: 20, header: '#'}),
{id:'text',header: "Text", width: 150, sortable: true, dataIndex: 'text'},
{id:'is_online',header: "Is Online?", width: 70, sortable: true, dataIndex: 'is_online'},
{id:'deadline',header: "Deadline", width: 130, sortable: true, dataIndex: 'deadline', xtype: "datecolumn", format: "Y-m-d"}
],
stripeRows : true,
height : 550,
title : 'Questions',
});
var gridSearch = new Ext.Panel({
stripeRows : true,
frame : true,
style : 'padding-bottom: 5px',
height : 250,
title : 'Search filter',
items : [{
xtype : 'checkbox',
id : 'is_for_online',
boxLabel : 'Показать только ОНЛАЙН',
inputValue : '1'
},{
xtype : 'datefield',
id : 'date_s',
allowBlank : true,
emptyText : 'Выберите дату С',
name : 'deadline',
width : 140,
editable : false,
format : 'Y-m-d'
},{
xtype : 'datefield',
id : 'date_s',
allowBlank : true,
emptyText : 'Выберите дату С',
name : 'deadline',
width : 140,
editable : false,
format : 'Y-m-d'
},{
xtype : 'button',
text : 'Go!',
handler : function () {
//var searchValueDate1 = Ext.getCmp("date_s").getValue();
//var searchValueDate2 = Ext.getCmp("date_po").getValue();
//var date_s = searchValueDate1.format('Y-m-d');
//var date_po = searchValueDate2.format('Y-m-d');
//store.filter("deadline", date_s)//, date_po);
alert(daterange);
}
},
]
});
You can also use multiple filters by same property, but add different id to each filter.
This makes much clear code.
store.filter([
{
id: "deadlineStart",
property: "deadline",
operator: ">",
value: new Date(2017, 0, 1)
},
{
id: "deadlineEnd",
property: "deadline",
operator: "<",
value: new Date()
}
]);
So what you want to do is have a user select a start and end date and in the grid filter out and show only the records with deadline dates between that range? Say you have field where the user enters the date range and click a button to filter on the filter button click. Get the date range from the two fields (I assume you'll have logic to make sure the user has enter a valid date range ie the start date is before the end date etc.)
Then try the following:
On the button click handler below
var grid = Ext.getCmp('grid');//Get the grid
var store = grid.store; //get the store from the grid to filter
//This method loops through each record return true to keep the record false to filter it //out
store.filterBy(function(rec, id){
var startDate = Ext.getCmp('dateFieldStart');
var endDate = Ext.getCmp('dateFieldEnd');
var deadLineDate = rec.data.deadline;
//Then here I'm not going to write all the code you need to see if the date of the record //is between the start and end range if so return true to keep the row in the grid and //return false to filter it out
if(in the range){
return true;
}else {
return false.
}
});
Here my example:
Ext.create('Ext.grid.Panel', {
id: 'destinationsGrid',
features: [{
ftype: 'filters',
encode: false,
local: false, // defaults to false (remote filtering)
filters: [
{ type:'list', dataIndex: 'status',/* phpMode: true,*/ options: [[1,'Прошел'], [0, 'Не прошел'] ]}
]
}],
columns: [
{ text: 'ФИО', flex: 1, dataIndex: 'fio', filter: {type: 'string'} },
{ text: 'Дата начало', dataIndex: 'start_date', filter: { type: 'date' }, xtype: "datecolumn", format: "d.m.Y" },
...
tbar: [
{
xtype: 'textfield',
emptyText: 'Найти участника',
id: 'findUserInGrid',
width: 350,
listeners: {
change: function(data, record){
var value = record;
var grid = Ext.getCmp('destinationsGrid'),
filter = grid.filters.getFilter('fio');
if (!filter) {
filter = grid.filters.addFilter({
active: true,
type: 'string',
dataIndex: 'fio'
});
filter.menu.show();
filter.setValue(value);
filter.menu.hide();
} else {
filter.setValue(value);
filter.setActive(true);
}
}
}
}
and:
listeners: {
change: function(data, record){
var value = record;
var grid = Ext.getCmp('destinationsGrid'),
filter = grid.filters.getFilter('fio');
if (!filter) {
filter = grid.filters.addFilter({
active: true,
type: 'string',
dataIndex: 'fio'
});
filter.menu.show();
filter.setValue(value);
filter.menu.hide();
} else {
filter.setValue(value);
filter.setActive(true);
}
}
}