I can't find how to open the context menu correctly in a grid with checkbox columns. Whenever the right click is performed on a checkbox cell, the checkbox is toggled. This is not what one expects for a context menu.
onAdminListCellContextMenu: function(tableview, td, cellIndex, record, tr, rowIndex, e, eOpts) {
e.stopEvent(); // this is where the right click should have been stopped from toggling the button underneath!?
var sample = Ext.getCmp('AdminListContextMenu') || new Admin.view.AdminListContextMenu;
sample.showAt(e.xy);
}
Which is called from my Grid Panel:
xtype: 'gridpanel',
flex: 1,
id: 'AdminList',
store: 'AdminStore',
columns: [{
xtype: 'gridcolumn',
dataIndex: 'user',
text: 'User',
editor: {xtype: 'textfield'}
},{
xtype: 'checkcolumn',
dataIndex: 'admins',
text: 'Grant admin rights'
}],
listeners: {
cellcontextmenu: {
fn: me.onAdminListCellContextMenu,
scope: me
}
}
Try this and let me know the result.
xtype: 'gridpanel',
flex: 1,
id: 'AdminList',
store: 'AdminStore',
selModel: Ext.create('Ext.selection.CheckboxModel', {
selType: 'checkboxmodel',
mode: 'SIMPLE',
checkOnly: true,
allowDeselect: true,
ignoreRightMouseSelection: true
},
multiSelect: true,
columns: [{
xtype: 'gridcolumn',
dataIndex: 'user',
text: 'User',
editor: {xtype: 'textfield'}
},{
xtype: 'checkcolumn',
dataIndex: 'admins',
text: 'Grant admin rights'
}],
listeners: {
beforeitemmousedown: {
function(grid, record, item, index, e, eOpts) {
if (e.button == 0) {
allowSelection = true;
} else {
allowSelection = false;
return false;
}
}
},
cellcontextmenu: {
fn: me.onAdminListCellContextMenu,
scope: me
}
}
Ext.define('Ext.override.CheckColumn',{
override:'Ext.grid.column.Check',
processEvent:function(type, view, cell, recordIndex, cellIndex, e, record, row) {
if(type == "mousedown" && e.button > 0) return; // prevent mousedown event if mouse button not the left button.
return this.callParent(arguments);
}
});
Tested in ExtJS 6.0.1, use at your own risk.
Related
I have a grid looking something like this:
Ext.create('Ext.grid.Grid', {
title: 'myGrid',
store: 'myStore',
columns: [
{ text: 'Name', dataIndex: 'name'},
{ text: 'Running', dataIndex: 'running' },
{
xtype: 'actioncolumn',
text:'play or stop',
items:[
{
iconCls: 'x-fa fa-play-circle',
handler:function(grid, rowIndex, colIndex){ play(); }
}, {
iconCls: 'x-fa fa-stop-circle',
handler:function(grid, rowIndex, colIndex){ stop(); }
}
]
}
]
});
It works fine. In the third column there are two buttons: a "play button" and a "stop button". Now they are always visible but I want the play button to be visible only when running==false, and the stop button to be visible only when running==true. How can I achieve that?
You can use the getClass config, which can be specified for the actioncolumn itself or for child items of the actioncolumn. docs
Then you can just do something like this:
Ext.create('Ext.grid.Grid', {
title: 'myGrid',
store: 'myStore',
columns: [
{text: 'Name', dataIndex: 'name'},
{text: 'Running', dataIndex: 'running'},
{
xtype: 'actioncolumn',
text: 'play or stop',
items: [
{
getClass: function (value, metadata, record) {
return record.data.running ? '' : 'x-fa fa-play-circle';
},
handler: function (grid, rowIndex, colIndex) {
play();
}
}, {
getClass: function (value, metadata, record) {
return record.data.running ? 'x-fa fa-stop-circle' : '';
},
handler: function (grid, rowIndex, colIndex) {
stop();
}
}
]
}
]
});
This worked:
Ext.create('Ext.grid.Grid', {
title: 'myGrid',
store: 'myStore',
columns: [
{text: 'Name', dataIndex: 'name'},
{text: 'Running', dataIndex: 'running'},
{
xtype: 'actioncolumn',
text: 'play or stop',
items: [
{
getClass: function (value, metadata, record) {
return record.data.running ? 'x-fa fa-stop-circle' : 'x-fa fa-play-circle';
},
handler: function (grid, rowIndex, colIndex) {
playOrStop();
}
},
]
}
]
});
My checkbox column:
{
xtype: 'widgetcolumn',
text: 'Selection',
tdCls: 'actions',
header: 'Selection',
width: '5%',
dataIndex: 'selection',
widget: {
xtype: 'checkbox',
defaultBindProperty: 'disabled',
listeners: {
afterrender: function (chb) {
var rec = chb.getWidgetRecord();
chb.setValue(rec.get('selection'));
chb.on('change', this.checkHandler);
chb.setDisabled(rec.get('selection_disabled'));
},
scope: this
}
}
}
How get checkbox in cellclick grid event for set value proggramatically? In cellclick me need change value of checkbox(cbox.setValue(!cbox.getValue()); or the same).
Not sure if it is best solution, but you can do something like this:
{
xtype: 'widgetcolumn',
dataIndex: 'checked',
flex: 1,
text: 'Checked',
widget: {
xtype: 'checkbox'
},
onWidgetAttach: function(column, widget, record) {
// Make sure your property / id pair is unique
// You can use Ext.id() to generate id for your record and widget
widget.widgetId = record.get('id');
}
}
and
grid.on('cellclick', function(view, td, cellIndex, record) {
var rowWidget = Ext.ComponentQuery.query('checkbox[widgetId=' + record.get('id') + ']')[0];
if(rowWidget) {
rowWidget.setValue(!rowWidget.getValue());
}
});
Working fiddle
My application is in MVC.
I have a grid with columns, and one of these columns has a with a renderer. This grid opens when the user clicks on an other grid.
When I load my application and I click to open this grid, this column (and the others after) don't load. But when I close and I re-open this grid, the columns are loaded.
I don't know where the problem is (moreover, this problem doesn't appear on the development server...)
I do a console.log(Ext.getStore('sTypesJours')) : I have some records
Then I do a console.log(Ext.getStore('sTypesJours').query('uid', val, false, false, true)) : I have no records the first time, but after re-open it works...
This is the code of my grid:
Ext.define('KGest.view.grille.Modif', {
extend: 'Ext.grid.Panel',
xtype: 'grillemodif',
title: 'Elements déjà saisis',
store: 'sGrilleModif',
dockedItems: [
{
xtype: 'toolbar',
dock: 'bottom',
itemId: 'toptoolbarService',
items: [
{
xtype: 'button',
id: 'save-button-grillemodif',
text: 'Sauver les modifications',
iconCls: 'x-icon-save',
action: 'update',
dock: 'top',
scope: this
}
]
}
],
selType: 'rowmodel',
plugins: [
Ext.create('Ext.grid.plugin.CellEditing', {
clicksToEdit: 1
})
],
columnLines: true,
viewConfig: {
deferEmptyText: false,
emptyText: 'Aucune donnée déjà saisie'
},
initComponent: function() {
var me = this;
me.selModel = Ext.create('Ext.selection.CheckboxModel', {
listeners: {
selectionchange: function(sm, selections) {
Ext.getCmp('validall-button-grillemodif').setDisabled(selections.length === 0);
Ext.getCmp('supprall-button-grillemodif').setDisabled(selections.length === 0);
}
},
injectCheckbox: 7 // position de la colonne des checkbox
});
Ext.apply(me, {
columns: [
{
text: 'Journée',
dataIndex: 'journee',
allowBlank: false,
xtype: 'datecolumn',
format: 'd/m/Y',
width: 100,
editor: {
xtype: 'datefield',
submitFormat: 'Y-m-d'
}
},
{
text: 'Type de jour',
dataIndex: 'uid_types_saisies',
flex: 1,
editor: {
xtype: 'combobox',
store: Ext.create('KGest.store.sTypesJours'),
valueField: 'uid',
displayField: 'libelle',
typeAhead: true,
queryMode: 'remote',
emptyText: 'Sélectionnez un type de jour',
listeners: {
beforequery: function(queryEvent, eOpts) {
var tabFilter = new Array();
tabFilter[0] = {"property": "uid_salaries", "value": Ext.getCmp('uid_salaries').getValue()};
queryEvent.combo.store.proxy.extraParams.filter = JSON.stringify(tabFilter);
}
}
},
renderer: function(val) {
if (val > 0) {
var srvStore = Ext.getStore('sTypesJours');
detail = srvStore.query('uid', val, false, false, true);
sortie = detail.getAt(0).data.code;
}
return sortie;
}
},
{
text: '1/2<br/>jour',
dataIndex: 'demi_jour',
xtype: 'checkcolumn',
width: 50
}
]
});
me.callParent(arguments);
}
});
Does anyone have any ideas?
Best I can offer (6 months after question asked) is this:
timing is everything, a field 'renderer' formats the cell-data at onload() time - meanwhile, instantiating and retrieving data to the store within the renderer function (when store-array is not-yet populated) returns undefined, by the time the next grid-load occurs, voila, there's the populated store, you get results from the query..
Probably solved this long ago, but load the store (autoload: true) or instantiate 'store' outside scope of grid-definition (before layout/renderer's are invoked)
I have my ExtJS 4.2.1 MVC Application.
Inside my app, I have a grid with a toolbar. The toolbar has 2 buttons, "Add New" and "Edit Record".
Inside my Controller.js I listen for my toolbar buttons click events.
this.control({
'toolbar #newRecord': {
click: this.addRecord
},
'toolbar #editRecord': {
click: this.editRecord
},
'[xtype=editshiftcode] button[action=commit]': {
click: this.saveRecord // here I have to add or edit
}
}
Then I have Window that I want to use for editing and adding records:
Ext.define('App.view.EditShiftCode', {
extend: 'Ext.window.Window',
alias: 'widget.editshiftcode',
height: 250,
width: 550,
title: 'Add / Edit Shift',
modal: true,
resizable: false,
layout: 'fit',
glyph: Glyphs.PENCIL,
initComponent: function() {
var me = this;
Ext.applyIf(me, {
items: [{
xtype: 'container',
//height: 175,
layout: {
type: 'hbox',
align: 'strech'
},
items: [{
xtype: 'form',
bodyPadding: 10,
autoScroll: false,
itemId: 'editForm',
defaults: { // defaults are applied to items, not the container
allowBlank: false,
allowOnlyWhitespace: false,
msgTarget: 'side',
xtype: 'textfield'
},
items: [
{
xtype: 'textfield',
name: 'ShiftCode',
fieldLabel: 'Code'
},
{
xtype: 'textfield',
name: 'Description',
fieldLabel: 'Description'
},
{
xtype: 'hiddenfield',
name: 'ShiftType'
},
{
xtype: 'hiddenfield',
name: 'ShiftTypeId'
},
{
xtype: 'textfield',
name: 'Hours',
fieldLabel: 'Hours per Day'
},
{
xtype: 'colorcombo',
name: 'ColorHex',
fieldLabel: 'Color'
},
{
xtype: 'checkbox',
fieldLabel: 'Active',
name: 'IsActive',
}
],
}]
}],
buttons: [
{
text: 'OK',
action: 'commit',
glyph: Glyphs.SAVE
},
{
text: 'Cancel',
action: 'reject',
glyph: Glyphs.CANCEL
}]
});
me.callParent(arguments);
},
});
My editRecord function is:
editRecord: function (button, e, options) {
var me = this;
var window = Ext.create('App.view.EditShiftCode');
window.show();
},
My addRecord function is:
addRecord: function (button, e, options) {
var me = this;
var window = Ext.create('App.view.EditShiftCode');
window.show();
},
My saveRecord function is:
saveRecord: function (button, e, options) {
// here i need to know what operation im going to perform.
// if Im going to edit then I have to update my form record to my store record
// if im going to add then I need to add a new item to my store.
}
Is this correct? To use the same function to perform 2 different actions? And if so, how can I know what action am I going to perform and how to do it?
Thanks
This way always worked for me:
User selects a record in the grid
User clicks "Edit record"
I use loadRecord to load the selected record in the form
When he clicks OK I call updateRecord
If user clicks "Add record" I create a new blank record and go to step 3
If he clicks OK after adding record, I just add the new record to the grid - you can easily know if the record is new or existing by checking phantom flag. So if record.phantom === true then it is new.
I have an ExtJS grid with a toolbar button to save the date. The save works and the data is stored. But the grid is not refreshed. How do I reload the grid data after the save?
Ext.define('MyLodge.view.content.MemberGrid', {
extend: 'Ext.grid.Panel',
alias: 'widget.membergrid',
initComponent: function(){
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing');
var store = Ext.create('MyLodge.store.Members');
Ext.apply(this, {
height: this.height,
plugins: [rowEditing],
store: store,
stripeRows: true,
columnLines: true,
columns: [{
id :'id',
text: 'ID',
width: 40,
sortable: true,
dataIndex: 'id'
},{
text : 'Name',
flex: 1,
sortable : true,
dataIndex: 'name',
field: {
xtype: 'textfield'
}
},{
text : 'E-Mail',
width : 150,
sortable : true,
dataIndex: 'email',
field: {
xtype: 'textfield'
}
},{
text : 'Href',
width : 200,
sortable : true,
dataIndex: 'href',
field: {
xtype: 'textfield'
}
}],
dockedItems: [{
xtype: 'toolbar',
items: [{
text: 'Add',
iconCls: 'icon-add',
handler: function(){
// empty record
store.insert(0, new MyLodge.model.Member());
rowEditing.startEdit(0, 0);
}
}, {
text: 'Delete',
iconCls: 'icon-delete',
handler: function(){
var selection = grid.getView().getSelectionModel().getSelection()[0];
if (selection) {
store.remove(selection);
}
}
},'-',{
text: 'Save',
iconCls: 'icon-save',
handler: function(){
store.sync();
}
}]
}]
});
this.callParent(arguments);
}
});
You can load store in callback of sync
store.sync({
success: function( response ) {
store.load();
}
});
You will probably want to call store.reload() in a callback from store.save() (what is store.save() anyway? it is not part of Ext.data.Store interface)