I have a dgrid like following code, my second field is a Tree, I need call a XHR when user to click tree's icon. How can I catch this event?
Thanks
var CustomGrid = declare([OnDemandGrid, Keyboard, Selection, Pagination]);
var grid = new CustomGrid({
columns: [
selector({label: "#", disabled: function(object){ return object.type == 'DOCx'; }}, "radio"),
{label:'Id', field:'id', sortable: false},
tree({label: "Title", field:"title", sortable: false, indentWidth:20}),
{label:'Count', field:'count', sortable: false}
],
store: memoryStore,
pagingLinks: false,
pagingTextBox: true,
firstLastArrows: true,
pageSizeOptions: [10, 15, 25],
selectionMode: "single", // for Selection; only select a single row at a time
cellNavigation: false // for Keyboard; allow only row-level keyboard navigation
}, "grid");
I have found the solution looking at the dojo's code.
There is a file called mouse.js in dgrid/util, there you can find others examples like these:
enterRow: handler(".dgrid-content .dgrid-row", "mouseover"),
enterCell: handler(".dgrid-content .dgrid-cell", "mouseover"),
enterHeaderCell: handler(".dgrid-header .dgrid-cell", "mouseover"),
leaveRow: handler(".dgrid-content .dgrid-row", "mouseout"),
leaveCell: handler(".dgrid-content .dgrid-cell", "mouseout"),
leaveHeaderCell: handler(".dgrid-header .dgrid-cell", "mouseout"),
So, for my case I have just added:
clickCell: handler(".dgrid-content .dgrid-expando-icon", "click"),
dblclickCell: handler(".dgrid-content .dgrid-cell", "dblclick"),
Now you can test the new events in Grid_mouseevents.html in dgrid/test.
regards.
Related
I am using "Jquery inputpicker plugin" which its references can be find here.
I use this plugin for dropdown menus. I initiate my drop down using below code:
$('#test').inputpicker({
data:[
{value:"1",text:"USD"},
{value:"2",text:"EUR"},
{value:"3",text:"CNY"}
],
fields:[
{name:'value',text:'Id'},
{name:'text',text:'Title'}
],
autoOpen: true,
headShow: false,
filterOpen: true,
fieldText : 'text',
fieldValue: 'value'
});
I can set selected item of my list by code:
$('#test').inputpicker('val', 1); // selecting "USD"
after setting the value of my field , when users try to open the drop down and look for another item, there is no item visible but "USD". For selecting another item, user should erase all characters manually, then other items will be displayed.
I am looking for a way to show all items after setting selected item.
I have created a sample of my code here:
https://jsfiddle.net/6eL9pfdw/
Hacky but it works:
Set the filterOpen: false, this will prevent filtering the data on the first open.
Bind to focus event and set the filterOpen = true. This will re-enable the filtering.
$(document).ready(function(){
$('#test').inputpicker("val" , "1");
});
$('#test').inputpicker({
data:[
{value:"1",text:"USD"},
{value:"2",text:"EUR"},
{value:"3",text:"CNY"}
],
fields:[
{name:'value',text:'Id'},
{name:'text',text:'Title'}
],
autoOpen: true,
headShow: false,
filterOpen: false,
fieldText : 'text',
fieldValue: 'value'
});
$('#inputpicker-1').on("focus", function() {
$('#test').inputpicker("set" , "filterOpen", true);
});
I think, you should deactivate the filter at the start of the code otherwise, it will display only what is provided according to the content of the textbox.
According to the document of InputPicker, setting filterOpen to false deactivates filter and all your data will be displayed.
More precisely, you only have to set it to false in your initial code
$(document).ready(function(){
$('#test').inputpicker("val" , "1");
});
$('#test').inputpicker({
data:[
{value:"1",text:"USD"},
{value:"2",text:"EUR"},
{value:"3",text:"CNY"}
],
fields:[
{name:'value',text:'Id'},
{name:'text',text:'Title'}
],
autoOpen: true,
headShow: false,
filterOpen: false,
fieldText : 'text',
fieldValue: 'value'
});
Fiddle with the problem is here https://fiddle.sencha.com/#view/editor&fiddle/2o8q
There are a lot of methods in the net about how to locally filter grid panel that have paging, but no one is working for me. I have the following grid
var grid = Ext.create('Ext.grid.GridPanel', {
store: store,
bbar: pagingToolbar,
columns: [getColumns()],
features: [{
ftype: 'filters',
local: true,
filters: [getFilters()],
}],
}
Filters here have the form (just copy pasted part of my filters object)
{
type: 'string',
dataIndex: 'name',
active: false
}, {
type: 'numeric',
dataIndex: 'id',
active: false
},
The store is the following
var store = Ext.create('Ext.data.Store', {
model: 'Store',
autoLoad: true,
proxy: {
data: myData,
enablePaging: true,
type: 'memory',
reader: {
type: 'array',
}
},
});
Here myData - comes to me in the form of
["1245", "Joen", "Devis", "user", "", "email#com", "15/6/2017"],
["9876", "Alex", "Klex", "user", "", "email#com", "15/6/2017"],[...
Also I have the the pagingToolbar
var pagingToolbar = Ext.create('Ext.PagingToolbar', {
store: store, displayInfo: true
});
So all the elements use the store I declared in the top. I have 25 elements per grid page, and around 43 elements in myData. So now I have 2 pages in my grid. When I am on first page of grid and apply string filter for name, for example, it filters first page (25 elements), when I move to 2d page, grid is also filtered, but in scope of second page. So as a result each page filters seperately. I need to filter ALL pages at the same time when I check the checkbox of filter, and to update the info of pagingToolbar accordingly. What I am doing wrong?
Almost sure that it is a late answer, but I have found the local store filter solution for paging grid you are probably looking for:
https://fiddle.sencha.com/#fiddle/2jgl
It used store proxy to load data into the grid instead of explicitly specify them in store config.
In general:
create empty store with next mandatory options
....
proxy: {
type: 'memory',
enablePaging: true,
....
},
pageSize: 10,
remoteFilter: true,
....
then load data to the store using its proxy instead of loadData
method
store.getProxy().data = myData;
store.reload()
apply filter to see result
store.filter([{ property: 'name', value: 'Bob' }]);
See President.js store configuration in provided fiddle example for more details.
Hope it helps
I've created an Ext.tree.Panel view.
Ext.define('MyApp.requests.view.QueryRequestsGridView', {
extend: 'Ext.tree.Panel',
useArrows: true,
rootVisible: false,
singleExpand: true,
bind: {
store: '{queryRequestsGrid}'
},
viewConfig:{
markDirty: false
},
columns: [
{ text: 'Id', dataIndex: 'id', flex: 3},
{ xtype: 'treecolumn', text: 'Name', dataIndex: 'name', flex: 6},
{ text: 'ControlType', dataIndex: 'controlType', flex: 4, sortable: false},
{ text: 'Description', dataIndex: 'description', flex: 6}
],
dockedItems: [{
xtype: 'pagingtoolbar',
bind: {
store: '{queryRequestsGrid}'
},
displayInfo: true
}]
}]
});
As I can see from the docs the store of Ext.tree.Panel should be Ext.data.TreeStore.
Ext.define('MyApp.requests.model.QueryRequestsGridModel', {
extend: 'Ext.data.TreeModel',
fields: [
{name: 'id'},
{name: 'name'},
{name: 'controlType'},
{name: 'description'}
]
});
Ext.define('MyApp.requests.store.QueryRequestsGridStore', {
extend: 'Ext.data.TreeStore',
model: 'MyApp.requests.model.QueryRequestsGridModel',
pageSize: 10,
alias: 'store.queryRequestsGrid',
root: {
expanded: false
},
remoteSort: true,
proxy: {
startParam: 'start',
limitParam: 'limit',
pageParam: undefined,
sortParam: undefined,
noCache: false,
type: 'ajax',
url: 'ucis.json'
}
});
Now on view creation the TreeStore data is requested using the following url without start and limit params but with nodeParam instead:
ucis.json?node=root
If to replace Ext.data.TreeStore with Ext.data.Store the following url will be sent:
ucis.json?offset=0&limit=10
The question is: does a treestore support start and limit pagingtoolbar parameters?
You can easily paginate a list. But the concept of tree pagination isn't disambiguous, I fear.
When thinking of the tree like an indented list, there would evidently be pages with leaves which are neither root nor have parents that have been sent to the client (because they are not on the page you requested). But the TreeStore does not work like an indented list; it works with a root and child nodes. This is why there is no builtin pagination support for TreeStore. Furthermore, PagingToolbar can only work with a list of nodes, not with a tree.
As per Pagination in Ext Tree, TreeStore does not require a full tree; it can work with a tree that is not fully loaded, and can dynamically fetch child nodes of a certain node whenever you expand the node. This is what you are using.
When thinking of every node's child nodes as a list, there is no builtin way to split the 1000 child nodes of a node into pages automatically. You can, however, extend the TreeStore to allow for that; there is no hard technical boundary against it. But you would have to extend the TreeGrid with a BufferedRenderer as well, which is not as easy as it may sound. The biggest hurdle would be using pagingToolbar, you won't be easily able to use that or extend from it, since it binds to the grid and works with that, but you need pagination on every node's child list. Because, if your root has a list of 1000 nodes and you open one of these nodes with 500 child nodes, how would the pagingToolbar know which node's children you want to page through?
Answering to my own question:
Yes, it is possible to send start and limit parameters from viewcontroller (for example, on afterrender event) using store.load
store.load({
params: {
start: 0,
limit: store.pageSize
}
});
The TreeStore will not send those parameters itself on the first load because does not support pagination from the box.
I'm seeing an issue with a combobox where I have a listener for the 'change' event. When the event fires it runs a function that filters a store that powers another combobox to filter the values that are available in the 2nd combobox.
The idea is that when you pick from a short list in the first combobox, it pares down the choices in the second combobox.
When the form loads, you can click the second combobox and see all the choices, that works great. When you then select something in the first combobox and then click the second combobox again, you see the appropriate shortened list but it's grayed out and the 'loading...' thing just spins and will never go away.
If you load the form and pick something in the first combobox and then click the second combobox it will filter and show fine but you run into the issue of the loading problem I described above if you try to change your selection in the first box and click the second combobox again.
Please see the code below, I have this setup working on another screen and it doesn't seem to have this issue.
I've got an ext store created like the following:
var comboBreaker = Ext.create('Ext.data.Store', {
autoLoad: false,
remoteSort: true,
remoteFilter: true,
fields: [{
name: 'id',
mapping: 'item_id',
type: 'int',
useNull: false},
'item_display_number','item_name', 'line_item_type_id', 'item_description'
],
proxy:{
type:'ajax',
url: '/invoicer/data/getlineitems',
reader: {
type: 'json',
successProperty: 'success',
root: 'results',
totalProperty: 'totalCount'
},
sorters:[{
property:'item_display_number',
direction:'ASC'
}]
}
});
This store powers a combobox, like so:
Ext.define('Writer.Form', {
extend: 'Ext.form.Panel',
alias: 'widget.writerform',
requires: ['Ext.form.field.Text'],
initComponent: function(){
this.addEvents('create');
Ext.apply(this, {
activeRecord: null,
frame: true,
title: 'Line Item',
id: 'writerform',
fieldDefaults: {
anchor: '100%',
labelAlign: 'right'
},
items: [{
xtype: 'combobox',
fieldLabel: 'Item #',
name: 'item_number',
store: comboBreaker,
displayField: 'item_display_number',
valueField: 'id',
allowBlank: false,
forceSelection: true
},{
xtype: 'combobox',
fieldLabel: 'Item Type',
name: 'item_type',
id: 'item_type',
displayField: 'line_item_type',
valueField: 'id',
store: invoicer_lineItemTypeStore,
forceSelection: true,
labelWidth: 75,
width: 200,
listeners: {
change: {
fn: function() {
itemNumberFilter(comboBreaker);
}
}
}
}]
});
The itemNumberFilter() function takes a store and does filtering on it, here is that code:
function itemNumberFilter( store ) {
var id = Ext.getCmp('item_type').getValue();
store.remoteFilter = false;
store.clearFilter();
if ( id ) {
store.filter('line_item_type_id', id);
}
store.remoteFilter = true;
store.removeAll();
store.load({
scope: this,
callback: function( records ) {
console.log('Loaded records!');
console.log(records);
}
});
}
I see the logged out records every time I change my selection in the first combobox and I can 'see' the results in the second combobox but they're always grayed out with the 'loading..' GIF showing.
Edit: Video example: http://screencast.com/t/cUSHyFE6FIV
Edit: I believe this is the solution:
lastQuery: '',
listeners: {
beforequery: {
fn: function(query) {
delete this.lastQuery;
}
}
}
Adding this to the combobox config fixes the issue.
Edit2: I ran into a second bug introduced by this, it was fixed by adding:
this.clearValue();
to the beforequery function (above delete this.lastQuery). This clears the value of the combobox each time the drop down arrow is clicked.
Let's say you select item x in combo_1 and then item a in the pared down list in combo_2. You then change the selection in combo_1 to y, which then changes the list of items again in combo_2. Is a available in the new list in combo_2 that results from selecting item y in combo_1? Maybe it is an issue of trying to keep an item selected when it no longer exists in the list available to the combo.
Have you tried clearing the selection in combo_2 before applying the filter?
You can dynamically load the store of the second combox box but be sure to set the second combox box to "local".
I try to use ComboBox on FormPanel, it is defined like this:
{
xtype: 'combo',
name: 'Reasons',
store: new Ext.data.ArrayStore({
id: 0,
fields: ['myId', 'displayText'],
data: [
[1, 'Reason 1'],
[2, 'Second Reason'],
[3, 'Something else']
]
}),
typeAhead: false,
mode: 'local',
valueField: 'myId',
displayField: 'displayText',
allowBlank: false,
editable: false,
forceSelection: true
}
I would like to act like a ordinary select element, when I have editable as false I not able to re-select anymore, when as true ( default ) I need to remove selection ( by backspace or delete ) in order to re-select.
What else I should turn off in order to downgrade combobox to select or shpuld I consider to use other component instead ?
My concern is if I really need ordinary select (not quite ordinary - ability to have store and manipulate options is very cool) - combo seems to me next level element what got too many features which I need to turn off and combo is rendered as input with arrow down image what trigger all action.
My question is:
Is it ExtJS element what is using HTML select tag, acting as select, rendering as select ?
The trick is to use triggerAction: 'all' - it forces the combo dropdown to show all items when you click the down-arrow icon (trigger).
That's probably the most counter-intuitive config option of ExtJS. And it's impossible to figure out what it really does by reading the docs. And like you say, to get a simple combo, you have to specify a myriad of config options, just to turn the fancy stuff off.
The ExtJS guys have promised to fix this in ExtJS 4, but until then I suggest you create your own ComboBox class that's configured the way most often needed in your app. For example I have something like this in my current project:
/**
* Simple combo, that just allows to choose from a list of values.
*/
var StaticComboBox = Ext.extend(Ext.form.ComboBox, {
mode: 'local',
triggerAction: 'all',
editable: false,
valueField: 'value',
displayField: 'label',
/**
* #cfg {[[String]]} data
* Items in combobox as array of value-label pairs.
*/
data: [],
initComponent: function() {
this.store = new Ext.data.ArrayStore({
fields: ['value', 'label'],
data: this.data
});
StaticComboBox.superclass.initComponent.call(this);
}
});
Having that, I can create a simple combo with just a few lines:
new StaticComboBox({
name: 'Reasons',
data: [
[1, 'Reason 1'],
[2, 'Second Reason'],
[3, 'Something else']
]
});