EXTJS checkcolumns disable on click - extjs

I have two EXT JS check columns like this:
var maleColumn = new Ext.grid.CheckColumn({
dataIndex: 'male',
headerId: 'male'
})
maleColumn .on('click', function(s, e, t, record) {...})
var femaleColumn = new Ext.grid.CheckColumn({
dataIndex: 'female',
headerId: 'female'
})
femaleColumn .on('click', function(s, e, t, record) {...})
Now I need to write an onClick event so that when one of these is clicked, the other one is disabled. How can I do it?

First, I should say that's a bit strange to have two CheckColumn for gender. Why not having one Column that has a combobox for user to select the gender?
But if you have to do so, I have a solution. My solution is based on Extjs 3.2.1.
//First, extend Ext.ux.grid.CheckColumn
MyCheckColumn = Ext.extend(Ext.ux.grid.CheckColumn,{
//The reference to the related dataIndex
relatedIndex : null,
//Override onMouseDown method
onMouseDown : function(e, t){
if(Ext.fly(t).hasClass(this.createId())){
e.stopEvent();
var index = this.grid.getView().findRowIndex(t);
var record = this.grid.store.getAt(index);
/*
* By checking the related record data, we can know if the other CheckColumn
* is checked or not (true/false means checked/unchecked).
* If false, we can then check the checkbox that is clicked.
*/
if(!record.data[this.relatedIndex])
record.set(this.dataIndex, !record.data[this.dataIndex]);
}
}
});
//Using MyCheckColumn and include relatedIndex in the config options.
var maleColumn = new MyCheckColumn({
dataIndex: 'male',
relatedIndex: 'female',
headerId: 'male'
});
var femaleColumn = new MyCheckColumn({
dataIndex: 'female',
relatedIndex: 'male',
headerId: 'female'
});
Though the solution works but I don't recommend it since the implementation may change when extjs upgrades. e.g. For extjs 3.3.1, you have to override another method but not onMouseDown:
processEvent : function(name, e, grid, rowIndex, colIndex){
if (name == 'mousedown') {
var record = grid.store.getAt(rowIndex);
//Do the changes here like the way I do above...
record.set(this.dataIndex, !record.data[this.dataIndex]);
return false; // Cancel row selection.
} else {
return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
}
}

Related

How to get actioncolumn icon component?

I'm searching two days and can't find how to get access to actioncolumn component (NOT html) on rowselect. I need to set event on icon click using Saki's component communication technique (source).
My column looks like:
I found a way how to show/hide buttons on change row selection (this code uses in GridPanel):
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
beforerowselect: function(grid, rowIndex, record) {
// 7 is the last cell index
var cell = grid.grid.getView().getCell( rowIndex, 7 );
//select icons in cell
var icons = Ext.DomQuery.select('.x-action-col-icon', cell);
//for each DOM element
Ext.each(icons, function(icon, index) {
currentIcon = Ext.get(icon);
//if not 1st button
if (index !== 0) {
//Delete class that hides. Class 'x-hidden' also works
currentIcon.removeClass('x-hide-display'); //show icon
}
});
},
rowdeselect: function(grid, rowIndex, record) {
// 7 is the last cell index
var cell = grid.grid.getView().getCell( rowIndex, 7 );
//select icons in cell
var icons = Ext.DomQuery.select('.x-action-col-icon', cell);
//for each DOM element
Ext.each(icons, function(icon, index) {
currentIcon = Ext.get(icon);
//if not 1st button
if (index !== 0) {
//Delete class that hides. Class 'x-hidden' also works
currentIcon.addClass('x-hide-display'); //show icon
}
});
}
}
});
Ok. Next. I want to show another window on click (set click event). But I don't know how to get access from Window/Viewport:
//get items
this.loanGrid = this.items.itemAt(0);
this.documentsGridWindow = this.items.itemAt(2);
//add events
this.loanGrid.on ({
scope: this,
afterrender: function() {
selModel = this.loanGrid.getSelectionModel();
selModel.on({
scope: this,
rowselect: function (grid, rowIndex, keepExisting, record) {
//HOW TO GET actioncolumn 2nd button here???
}
});
}
});
I also tried to set id to this icon on beforerowselect, but on rowselect this code Ext.getCmp('icon-id') returns undefined.
up() and down() functions not helps me too =(
HELP please! =)
p.s. Sad, but Ext.ComponentQuery works only from ExtJS 4.
So finally I re-wrote some parts of my application.
First we need to add some options to actioncolumn:
dataIndex: 'action',
id: 'action',
Grid row buttons show/hide now is independent of actioncolumn move:
/**
* buildSelectionModel
*/
buildSelectionModel: function() {
var sm = new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
scope: this,
rowselect: function(grid, rowIndex, record) {
this.toggleFirstButtonShowState(grid.grid, rowIndex);
},
rowdeselect: function(grid, rowIndex, record) {
this.toggleFirstButtonShowState(grid.grid, rowIndex);
}
}
});
return sm;
},
/**
* toggleFirstButtonShowState
*/
toggleFirstButtonShowState: function(grid, rowIndex) {
//'action' is data index of
var colIndex = this.getColumnIndexByDataIndex(grid, 'action');
console.log(colIndex);
// 7 is the last cell index
var cell = grid.getView().getCell( rowIndex, colIndex);
//select icons in cell
var icons = Ext.DomQuery.select('.x-action-col-icon', cell);
//for each DOM element
Ext.each(icons, function(icon, index) {
currentIcon = Ext.get(icon);
//if not 1st button
if (index !== 0) {
//Show/delete class that hides. Class 'x-hidden' also works
currentIcon.toggleClass('x-hide-display'); //show/hide icon
}
});
},
getColumnIndexByDataIndex: function(grid, dataIndex) {
//columns
gridColumns = grid.getColumnModel().columns;
for (var i = 0; i < gridColumns.length; i++) {
if (gridColumns[i].dataIndex == dataIndex) {
return i;
}
}
Viewport part:
//get selection model
selModel = this.loanGrid.getSelectionModel();
selModel.on({
scope: this,
rowselect: function (grid, rowIndex, keepExisting, record) {
//get second icon in actioncolumn
var icon = grid.grid.getColumnModel().getColumnById('action').items[1];
//save context
var self = this;
//add handler by direct set
icon.handler = function(grid, rowIndex, colIndex) {
//open documents window
self.documentsGridWindow.show();
};
}
});
All works as expected!

ExtJS Change actioncolumn icon from controller / handler

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.

Extjs grid grouping summary click event

I'm using Ext.grid.Panel with Ext.grid.feature.GroupingSummary. i need to add listener for summary row click event. Is there are any event for summary row click.
Ext.create('Ext.grid.Panel', {
features:[
Ext.create('Ext.grid.feature.GroupingSummary',{
ftype: 'groupingsummary'
})
],
As far as I can tell, there's nothing built-in to do that. You will have to catch the click event on the summary element yourself. That remains relatively easy. Things get complicated if you need to know the group of the summary that has been clicked...
You can use the getGroupName method of the feature. For that, you'll need to keep a reference to the grouping feature instance and, the joyful part, you'll have to find the group header element that matches the clicked summary element. To spice things up even a little more, the markup for group and summary elements seems to have changed drastically in Ext 4.2.
Here's the code of a listener (on the click event of summary element) which does all that.
function(e, target) {
// Find group element (header), for the clicked summary
var groupEl;
if (Ext.getVersion().isLessThan('4.2')) {
// Life used to be easy with everything being a row
// in the table (actual rows, group headers,
// summary row)...
groupEl = Ext.fly(target).prev('.x-grid-group-hd');
} else {
// But from Ext4.2, everything became complicated.
// Group headers & summary row seem to be embedded
// in the next or previous regular row... Since I
// haven't entirely understood the logic behind, I
// cannot guarantee this will work with all possible
// cases...
var row = Ext.fly(target).up('.x-grid-row');
while (row && !groupEl) {
groupEl = row.down('.x-grid-group-hd');
row = row.prev('.x-grid-row');
}
}
// We can get the group name from the group element,
// but we need a reference to the grouping feature
// instance...
var groupName = groupingSummary.getGroupName(groupEl);
// Here you are...
console.log('Group clicked: ' + groupName);
}
And here's a complete example, based on the grouping summary grid example from the doc.
Ext.define('TestResult', {
extend: 'Ext.data.Model',
fields: ['student', 'subject', {
name: 'mark',
type: 'int'
}]
});
var groupingSummary = Ext.create('Ext.grid.feature.GroupingSummary', {
groupHeaderTpl: 'Subject: {name}',
ftype: 'groupingsummary'
});
Ext.create('Ext.grid.Panel', {
width: 200,
height: 240,
renderTo: document.body,
features: [groupingSummary],
store: {
model: 'TestResult',
groupField: 'subject',
data: [{
student: 'Student 1',
subject: 'Math',
mark: 84
},{
student: 'Student 1',
subject: 'Science',
mark: 72
},{
student: 'Student 2',
subject: 'Math',
mark: 96
},{
student: 'Student 2',
subject: 'Science',
mark: 68
}]
},
columns: [{
dataIndex: 'student',
text: 'Name',
summaryType: 'count',
summaryRenderer: function(value){
return Ext.String.format('{0} student{1}', value, value !== 1 ? 's' : '');
}
}, {
dataIndex: 'mark',
text: 'Mark',
summaryType: 'average'
}]
,listeners: {
click: {
element: 'body'
,delegate: '.x-grid-row-summary'
,fn: function(e, target) {
// Find group element (header), for the clicked summary
var groupEl;
if (Ext.getVersion().isLessThan('4.2')) {
// Life used to be easy with everything being a row
// in the table (actual rows, group headers,
// summary row)...
groupEl = Ext.fly(target).prev('.x-grid-group-hd');
} else {
// But from Ext4.2, everything became complicated.
// Group headers & summary row seem to be embedded
// in the next or previous regular row... Since I
// haven't entirely understood the logic behind, I
// cannot guarantee this will work with all possible
// cases...
var row = Ext.fly(target).up('.x-grid-row');
while (row && !groupEl) {
groupEl = row.down('.x-grid-group-hd');
row = row.prev('.x-grid-row');
}
}
// We can get the group name from the group element,
// but we need a reference to the grouping feature
// instance...
var groupName = groupingSummary.getGroupName(groupEl);
// Here you are...
console.log('Group clicked: ' + groupName);
}
}
}
});
The goal of this answer is just to demonstrate the principles. You may want to organize this code in a better way... The cleanest would probably be to extend or override the GroupingSummary class.

Extjs 3.4 checkchange listener not working on Checkcolumn

The checkchange listener for my checkColumn is not working. Any ideas why not?
var checked = new Ext.grid.CheckColumn({
header: 'Test',
dataIndex: 'condition',
renderer: function(v,p,record){
var content = record.data['info'];
if(content == 'True'){
p.css += ' x-grid3-check-col-td';
return '<div class="x-grid3-check-col'+(v?'-on':'')+' x-grid3-cc-'+this.id+'"> </div>';
}
},
listeners:{
checkchange: function(column, recordIndex, checked){
alert("checked");
}
}
});
In Ext.ux.grid.CheckColumn, add this initialize method that register a checkchange event:
initComponent: function(){
Ext.ux.grid.CheckColumn.superclass.initComponent.call(this);
this.addEvents(
'checkchange'
);
},
Then in processEvent fire the event:
processEvent : function(name, e, grid, rowIndex, colIndex){
if (name == 'mousedown') {
var record = grid.store.getAt(rowIndex);
record.set(this.dataIndex, !record.data[this.dataIndex]);
// Fire checkchange event
this.fireEvent('checkchange', this, record.data[this.dataIndex]);
return false; // Cancel row selection.
} else {
return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
}
},
The resulting CheckColumn component should look like this:
Ext.ns('Ext.ux.grid');
Ext.ux.grid.CheckColumn = Ext.extend(Ext.grid.Column, {
// private
initComponent: function(){
Ext.ux.grid.CheckColumn.superclass.initComponent.call(this);
this.addEvents(
'checkchange'
);
},
processEvent : function(name, e, grid, rowIndex, colIndex){
if (name == 'mousedown') {
var record = grid.store.getAt(rowIndex);
record.set(this.dataIndex, !record.data[this.dataIndex]);
this.fireEvent('checkchange', this, record.data[this.dataIndex]);
return false; // Cancel row selection.
} else {
return Ext.grid.ActionColumn.superclass.processEvent.apply(this, arguments);
}
},
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' : '');
},
// Deprecate use as a plugin. Remove in 4.0
init: Ext.emptyFn
});
// register ptype. Deprecate. Remove in 4.0
Ext.preg('checkcolumn', Ext.ux.grid.CheckColumn);
// backwards compat. Remove in 4.0
Ext.grid.CheckColumn = Ext.ux.grid.CheckColumn;
// register Column xtype
Ext.grid.Column.types.checkcolumn = Ext.ux.grid.CheckColumn;
In ExtJS 3, the checkcolumn plugin does not actually use ExtJS's checkbox component, so checkbox events are not available. The checkcolumn is simply an extended grid column that has added a custom renderer to style the cell like a checkbox.
By default, the only events you can listen to are Ext.grid.Column's events (click, contextmenu, dblclick, and mousedown).
This answer to a similar question shows how to override the CheckColumn and add the beforecheckchange & checkchange events.
Simple Answer
Check box check or uncheck when user click on check box in extjs 3 grid.
use this property in grid: => columnPlugins: [1, 2],
I belive this property use in your code is wornig perfectly.
xtype:grid,
columnPlugins: [1, 2],

How can I add row numbers to an ExtJS grid?

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;
}
}
});

Resources