I am having trouble with creating context menu(right click). Can someone help me with the code?
My code:
var item = RMenu.add({
text: '$Delete',
id: 'Delete',
icon:'../Tce/Images/tcdtpDelete.gif',
handler:onItemClick,
tooltip:'$Delete'
});
listeners: {
cellcontextmenu: function(table, td, cellIndex, record, tr, rowIndex, e) {
Ext.create('Ext.menu.Menu',{
items:[{
text: 'Delete',
handler: function() {
table.getStore().remove(table.getSelectionModel().getSelection());
table.getStore().sync();
}
}]
}).showAt(e.pageX, e.pageY);
}
}
Related
How to create a filter in the grid headers?
I found this snippet: https://stackoverflow.com/a/22015160/5775332 and updated to compatibility with 6th version:
Ext.define('Fiddle.view.SearchTrigger', {
extend: 'Ext.form.field.Text',
alias: 'widget.searchtrigger',
requires: [
'Ext.form.trigger.Trigger'
],
defaultListenerScope: true,
triggers: {
search: {
handler: function(field, trigger, e) {
this.setFilter(this.up().dataIndex, this.getValue());
},
cls: 'x-form-search-trigger'
},
clear: {
handler: function(field, trigger, e) {
this.setValue('');
if(!this.autoSearch) this.setFilter(this.up().dataIndex, '');
},
cls: 'x-form-clear-trigger'
}
},
listeners: {
render: 'onTextfieldRender',
change: 'onTextfieldChange'
},
onTextfieldRender: function(component, eOpts) {
var me = this;
me.ownerCt.on('resize', function(){
me.setWidth(this.getEl().getWidth());
});
},
onTextfieldChange: function(field, newValue, oldValue, eOpts) {
if(this.autoSearch) this.setFilter(this.up().dataIndex, this.getValue());
},
setFilter: function(filterId, value) {
var store = this.up('grid').getStore();
if(value){
store.removeFilter(filterId, false);
var filter = {id: filterId, property: filterId, value: value};
if(this.anyMatch) filter.anyMatch = this.anyMatch;
if(this.caseSensitive) filter.caseSensitive = this.caseSensitive;
if(this.exactMatch) filter.exactMatch = this.exactMatch;
if(this.operator) filter.operator = this.operator;
console.log(this.anyMatch, filter);
store.addFilter(filter);
} else {
store.filters.removeAtKey(filterId);
store.reload();
}
}
});
The most difficult place - creation items with widget in column.
I cant reproduce it in Sencha Fiddle. How to do it?
First login to Sencha Fiddle using the Sencha Forum credentials. After this, copy-paste your code and save it. The updated url that you get after saving will be sharable. Please refer here for docs on Sencha Fiddle.
Fixed code: https://fiddle.sencha.com/#view/editor&fiddle/2820
Inside my extjs grid, when I right click I call a context menu. When I click on one of the items I want to launch a method in the controller. This all works successfully, problem is I want to pass the parent grid that this is being called from into the controller method. Can someone please show me how to do this?
This is my context menu
Ext.define('Example.ContextMenuTradematch', {
xtype: 'contextMenuTradematch',
extend: 'Ext.menu.Menu',
items: [
{
text: 'Match Trade',
iconCls: 'greenIcon',
listeners: {
click: {
fn: 'onMatchTrade',
params: {
param1: this
}
}
}
},
{
text: 'Delete Trade',
iconCls: 'deleteIcon',
listeners: {
click: 'onDeleteTrade'
}
}
]
});
then this is my controller method
onMatchTrade: function (event, target, options) {
debugger;
var me = this;
How can I access the grid that the event originated from?
--and this is how I add the context menu to the grid
title: 'Tradematch Results: UNMATCHED',
xtype: 'grid',
itemId: 'gridUnmatchedId',
ui: 'featuredpanel-framed',
cls: 'custom-grid',
margin: '0px 10px 0px 10px',
flex: 2,
width: '100%',
bind: {
store: '{myTM_ResultsStore}'
},
listeners: {
itemcontextmenu: 'showContextMenuTradematch'
},
and this is how the controller adds it...
getContextMenu: function (cMenu) {
if (!this.contextMenu) {
debugger;
this.contextMenu = this.getView().add({ xtype: cMenu });
}
return this.contextMenu;
},
showContextMenuTradematch: function (view, rec, node, index, e) {
e.stopEvent();
e.stopEvent();
debugger;
this.getContextMenu('contextMenuTradematch1').show().setPagePosition(e.getXY());
return false;
},
The easiest way to do this is when you create your Example.ContextMenuTradematch instance - that I'm assuming you do from a itemcontextmenu listener - then you could pass a reference to the grid.
itemcontextmenu: function (grid, record, item) {
// code to create your menu
// probably something like:
if (!grid.contextMenu) {
grid.contextMenu = Ext.create('Example.ContextMenuTradematch', {
ownerGrid: grid
});
}
grid.contextMenu.showBy(item);
}
If onMatchTrade was fired by clicking on an Ext.menu.Item instance then it's signature will be:
onMatchTrade: function (item, e) {
var menu = item.up('menu'),
grid = menu.ownerGrid;
console.log(grid);
}
There was a lot of guessing here. If this is not how you are creating your menu or calling the methods, adding a fiddle with the issue would help.
Here is a fiddle to use as template: https://fiddle.sencha.com/#view/editor&fiddle/24fc
Could you teach me how to call nested methods? Basic idea, i want to have a function inside a class that i can configure from outside by sending another folderSelector with different return path. But when right now i'm trying to do that extjs says to me:
[W] XTemplate evaluation exception: foldersSelector is not a function
Code example:
Ext.define('somepath.Some1', {
extend: 'somepath.SomeParent',
text: 'sometext',
foldersSelector: function(data){
return data.folders;
},
initComponent: function(){
...
this.callParent();
}
renderer: function(data){
bla bla bla / got data from somewhere
...
...
foldersSelector(data);
// with this.foldersSelector result the same!
}
});
You are missing this in your function. You need to call the function from the class object. Something like this:
Ext.define('MyApp.view.MyPanel', {
extend: 'Ext.panel.Panel',
alias: 'widget.mypanel',
height: 250,
width: 400,
title: 'My Panel',
defaultListenerScope: true,
listeners: {
render: 'onPanelRender'
},
onPanelRender: function(component, eOpts) {
// call using this
this.folderSelector();
// call using component
component.folderSelector();
},
folderSelector: function(data) {
console.log('Function')
}
});
Fiddle https://fiddle.sencha.com/#view/editor&fiddle/1mpe
In your case, you are in the grid column, you can't call this because that's the grid. You have to get the column.
Ext.define('MyApp.view.MyColumn3', {
extend: 'MyApp.view.SuperColumn',
alias: 'widget.mycolumn3',
id: 'myColumnId',
foldersSelector: function (data) {
console.log('I AM CALLED');
return data + '-SOSO'
},
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
// you have to get the column, there are many ways how to do so
var c = Ext.first('#myColumnId')
return c.foldersSelector(value)
}
// option without the id
renderer: function(value, metaData, record, rowIndex, colIndex, store, view) {
// this is the grid
var gridColumns = this.getColumns();
// we know the column index
var c = gridColumns[colIndex];
return c.foldersSelector(value)
}
});
Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/1mpo
In ExtJs, there are many options to filter a grid. There are two nice examples in the documentation, like referenced in this question.
Remote filtering
Local filtering
However, having the filter hidden in the default dropdown menu of Ext.ux.grid.FiltersFeature looks really awkward for me. A good ergonomic choice would to create search fields in the column headers, like #Ctacus shows in his question.
How can this be achieved ?
After quite much research through the sparse documentation, and thanks to great questions and answers in SO, I came up with a simple class, that adds this functionality and and allows for configurations.
It looks like this:
You add this field in your grid like this:
Ext.define('Sandbox.view.OwnersGrid', {
extend: 'Ext.grid.Panel',
requires: ['Sandbox.view.SearchTrigger'],
alias: 'widget.ownersGrid',
store: 'Owners',
columns: [{
dataIndex: 'id',
width: 50,
text: 'ID'
}, {
dataIndex: 'name',
text: 'Name',
items:[{
xtype: 'searchtrigger',
autoSearch: true
}]
},
The following configs are possible, and work like described in the doc for Ext.util.Filter:
anyMatch
caseSensitive
exactMatch
operator
additionnaly you can use autoSearch. If true, the filter searches as you type, if false or not set, one has to click on the search icon to apply the filter.
ExtJs 5 / 6 Source:
Ext.define('Sandbox.view.SearchTrigger', {
extend: 'Ext.form.field.Text',
alias: 'widget.searchtrigger',
triggers:{
search: {
cls: 'x-form-search-trigger',
handler: function() {
this.setFilter(this.up().dataIndex, this.getValue())
}
},
clear: {
cls: 'x-form-clear-trigger',
handler: function() {
this.setValue('')
if(!this.autoSearch) this.setFilter(this.up().dataIndex, '')
}
}
},
setFilter: function(filterId, value){
var store = this.up('grid').getStore();
if(value){
store.removeFilter(filterId, false)
var filter = {id: filterId, property: filterId, value: value};
if(this.anyMatch) filter.anyMatch = this.anyMatch
if(this.caseSensitive) filter.caseSensitive = this.caseSensitive
if(this.exactMatch) filter.exactMatch = this.exactMatch
if(this.operator) filter.operator = this.operator
console.log(this.anyMatch, filter)
store.addFilter(filter)
} else {
store.filters.removeAtKey(filterId)
store.reload()
}
},
listeners: {
render: function(){
var me = this;
me.ownerCt.on('resize', function(){
me.setWidth(this.getEl().getWidth())
})
},
change: function() {
if(this.autoSearch) this.setFilter(this.up().dataIndex, this.getValue())
}
}
})
For ExtJs 6.2.0, the following bug and its workaround is relevant to this, else the column cannot be flexed.
ExtJs 4 Source:
Ext.define('Sandbox.view.SearchTrigger', {
extend: 'Ext.form.field.Trigger',
alias: 'widget.searchtrigger',
triggerCls: 'x-form-clear-trigger',
trigger2Cls: 'x-form-search-trigger',
onTriggerClick: function() {
this.setValue('')
this.setFilter(this.up().dataIndex, '')
},
onTrigger2Click: function() {
this.setFilter(this.up().dataIndex, this.getValue())
},
setFilter: function(filterId, value){
var store = this.up('grid').getStore();
if(value){
store.removeFilter(filterId, false)
var filter = {id: filterId, property: filterId, value: value};
if(this.anyMatch) filter.anyMatch = this.anyMatch
if(this.caseSensitive) filter.caseSensitive = this.caseSensitive
if(this.exactMatch) filter.exactMatch = this.exactMatch
if(this.operator) filter.operator = this.operator
console.log(this.anyMatch, filter)
store.addFilter(filter)
} else {
store.filters.removeAtKey(filterId)
store.reload()
}
},
listeners: {
render: function(){
var me = this;
me.ownerCt.on('resize', function(){
me.setWidth(this.getEl().getWidth())
})
},
change: function() {
if(this.autoSearch) this.setFilter(this.up().dataIndex, this.getValue())
}
}
})
In my Grid, when I click on the Action button (the delete and edit button shown in the code below), I need to pop open a window without alerting the user with a Alert message;
In the following code I am using a HANDLER handler: buttonClicked and trying to access the row value i clicked from a different function below
buttonClicked :function (){...}
I don't know how to do this, can someone please help me ?
Can i access the row I clicked and display its name from the Controller class ?
CODE SNIPET
Ext.define('CountryAppTest.view.user.Gridview', {
extend: 'Ext.grid.Panel',
initComponent: function() {
this.store = 'store';
this.columns = [{
xtype: 'ac',
items: [{
icon: 'lib/extjs/examples/restful/images/delete.png',
handler: buttonClicked
}]
}, {
text: "username",
dataIndex: 'username'
}];
this.viewConfig = {
forceFit: true
};
this.callParent(arguments);
},
buttonClicked: function(grid, rowIndex, colIndex) {
var rec = grid.getStore().getAt(rowIndex);
Ext.Msg.alert("Info", "name " + rec.get('username'));
}
});
Add the parameters (grid, rowIndex, colIndex) into your buttonClicked declaration.