ExtJS combobox acting like regular select - javascript

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

Related

Extjs 4.2.1 Local filtering of Grid panel with Paging

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

Is it possible to send start and limit parameters in ajax request using Extjs 5 TreeStore?

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.

understanding store in ExtJS

I am new to ExtJS and I find documentation confusing, I need to get the first data from store, which I get from the report. How to do it correctly?
this.divisionList = new ....SimplestReportCombo({
fieldLabel: "Division",
allowBlank: false,
valueField: 'KEY',
displayField: store.load.get(0),
width: 200,
reportID: 'USER_ACCESS',
store : new Ext.data.ArrayStore({
fields: [{name: 'KEY'}],
data: [{name: 'VALUE'}]
}
)
});
Javascript Stores mostly resembles RDBMS tables. They have in memomy storage and they are helpful to perform various grid level operation like sorting , paging , shuffling , editing etc.
Lets come to your code now,
You dont need to load store get its elements.If you requirement is only to select 1st ellement from store then you can do that using getAt function like below:
this.divisionList = new ....SimplestReportCombo({
fieldLabel: "Division",
allowBlank: false,
valueField: 'KEY',
displayField: store.getAt(0),
width: 200,
reportID: 'USER_ACCESS',
store : new Ext.data.ArrayStore({
fields: [{name: 'KEY'}],
data: [{name: 'VALUE'}]
}
)
});
or else you can also use following store method if you want to render mere 1st element:
store.first()

Column Plugins(tree) Catch click event in dojo

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.

ExtJS4 combobox loading/store issue

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".

Categories