ExtJS - Remote filtering causes problems - javascript

a) Here's a JS fiddle to help show what's happening: http://jsfiddle.net/CKpPW/
b) To replicate the issue, select the first drop down and notice how the full name appears. Then expand the second drop down and notice how the display of the first drop down goes away.
My assumption is that this happens because both comboboxes use the same store so when a filter is applied to the store it applies to everything, and thus when that record no longer exists it defaults back to whatever the value is.
Is there anyway to make that not happen, aka even after a filter on a store the data in the combobox stays the same. I can't seem to find any details on dualing comboboxes like this.
Here's the listener that needs to happen on expand as I need the ability to filter each combobox differently:
listeners: {
expand: {
fn: function(){
names.clearFilter(true);
names.filter('id', 1);
}
}
},

Indeed, you're not supposed to share stores between components. That may be counter-intuitive, but store do not represent the whole data, but only the subset the component is currently working with. The interface to the whole data is the proxy.
component <=> store <=> proxy <=> actual data
So if you want to share data, what you need to share is the proxy, not the store.
Here's, for example, how to fix your fiddle:
var proxy = Ext.create('Ext.data.proxy.Memory', {
reader: 'json',
data : [
{'id':0,"FirstName":"Frédéric", "LastName":"Bastiat"},
{'id':1,"FirstName":"John", "LastName":"Alcatraz"},
{'id':2,"FirstName":"Nasha", "LastName":"Cartoga"}
//...
]
});
var store1 = Ext.create('Ext.data.Store', {
proxy: proxy,
fields: ['id','FirstName', 'LastName'],
remoteFilter:true,
remoteSort:true,
filters: [{property: 'id', value: 1}]
});
var store2 = Ext.create('Ext.data.Store', {
proxy: proxy,
fields: ['id','FirstName', 'LastName'],
remoteFilter:true,
remoteSort:true,
filters: [{property: 'id', value: 2}]
});
// Create the combo box, attached to the states data store
Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Choose Name',
store: store1,
id: 'nameCombo',
queryMode: 'local',
displayField: 'FirstName',
valueField: 'FirstName',
displayTpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<tpl if="FirstName">',
'{FirstName}',
'</tpl>',
' ',
'<tpl if="LastName">',
'{LastName}',
'</tpl>',
'</tpl>'),
renderTo: Ext.getBody()
});
// Create the combo box, attached to the states data store
Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Choose Name',
id: 'nameCombo2',
queryMode: 'local',
displayField: 'FirstName',
valueField: 'FirstName',
store: store2,
displayTpl: Ext.create('Ext.XTemplate',
'<tpl for=".">',
'<tpl if="FirstName">',
'{FirstName}',
'</tpl>',
' ',
'<tpl if="LastName">',
'{LastName}',
'</tpl>',
'</tpl>'),
renderTo: Ext.getBody()
});
Now, your next question will probably be about how to get your sever-side data into that client-side memory proxy... Unfortunately, the framework doesn't offer any solution out of the box.
The most straightforward way is probably to load your data once with a regular AJAX request, put it into a memory proxy, and pass this proxy to all your stores.
Or you can get creative and try to implement your own proxy that mixes loading from the server and caching on the client. That's quite simple to achieve by overriding the Memory proxy, but soon enough you'll be running into a bunch of tough questions... How to handle the caching for operations with different params? How to handle request params at all? What about the other CRUD operations, beyond read? Etc. If you want to give it a try anyway, you can look at this extension for inspiration (it is written for Touch, so you can't use it directly, but the principles are the same for ExtJS).

Related

Append option to combox without modifying data store

Is there a way to add an option to a combobox without modifying the underlying data store in any way? I have 2 combobox elements in my form. The only difference between the two comboboxes is that one has an additional 'All' option. For example:
var states = Ext.create('Ext.data.Store', {
fields: ['abbr', 'name'],
data : [{"abbr":"AL", "name":"Alabama"},
{"abbr":"AK", "name":"Alaska"},
{"abbr":"AZ", "name":"Arizona"}]
});
//The first combobox should load the data as is from the store above
Ext.create('Ext.form.ComboBox', {
fieldLabel: 'Choose State',
store: states,
queryMode: 'local',
displayField: 'name',
valueField: 'abbr',
renderTo: Ext.getBody()
});
//There should be a second combobox here that is almost identical
//to the one above, just appending an additional option (that says "All")
//to the top of the list
I'm aware that there are various ways to alter the store such as:
states.insert(0, [{
abbr: 'All',
name: 'All'
}])
However, I want to achieve this without altering the store, purely adding the option to the combobox itself. Is this possible?
UPDATE
I am aware that I could make the I could set the combobox 'emptyText' configuration option to 'All', but this is not what I want. I would like to have 'All' as an actual option.
Combo is a simple SELECT field of HTML. Without OPTION you cannot populate the dropdown.
Its not possible to achieve it without adding into store. Data you see in the combo comes from store.
According to the docs :
A combobox control with support for autocomplete, remote loading, and many other features.
A ComboBox is like a combination of a traditional HTML text field and a field; the user is able to type freely into the field, and/or pick values from a dropdown selection list. The user can input any value by default, even if it does not appear in the selection list; to prevent free-form values and restrict them to items in the list, set forceSelection to true.
The selection list's options are populated from any Ext.data.Store, including remote stores. The data items in the store are mapped to each option's displayed text and backing value via the valueField and displayField configurations, respectively.
I have already made comboboxes with "All", I hope I get it right, haven't got the source code available right now, but to create an "All" option for one of the comboboxes, in ExtJS 6 you have to do something like this:
var storeWithAll = Ext.create('Ext.data.Store',{
url:
proxy: etc.
listeners:{
load:function(store) {
// Add the "All" record after every load!
store.insert(0, [{
abbr: 'All',
name: 'All',
special:true
}]);
}
}
});
var storeWithoutAll = Ext.create('Ext.data.ChainedStore',{
// ChainedStore has the same data as the source:
source: storeWithAll,
filters:[{
// Filter away the "All" record
filterFn:function(item) {return !item.get("special");}
}]
});
Ext.create('Ext.form.field.ComboBox',{
store: storeWithAll, // Use the store with "All" record
...
});
Ext.create('Ext.form.field.ComboBox',{
store: storeWithoutAll, // Use the store without "All" record
...
});

bindStore breaks combobox

Among the other form fields i have(the combobox is an extension of the standard combobox with extra config options):
marker: new Forms.ui.ComboBox({
fieldLabel: _('Marker'),
displayField: 'name',
valueField: 'id',
store: new Ext.data.JsonStore({
fields: ['name', 'id','resellerid'],
data: [
{'name':_('Default'), 'id': 0, 'resellerid': 0}
]
})
})
Now when i need to use bindStore in a function that is called separately and has a jsonStore passed to it(store):
this.fields.marker.bindStore(store);
However, while the store is populated - im unable to select anything. I moved the store to the same script to test it - and set it directly to the combobox config as 'store:' - it works.
So the problem comes from bindstore it seems.
What am i missing?
Apparently it was the quotes around the data property names that broke it.

sencha touch load store manually

Simple use case: I want to manually control when I load the store. When the store is loaded, I want the data to populate the list. However, I cannot get it to work.
When I set autoLoad to true on the store, it works. If I remove autoLoad, and add this to the view nothing happens.
List config:
{
xtype: 'list',
fullscreen: true,
disableSelection: true,
store: 'NewsStore',
itemId: 'newsList',
itemTpl: '<li><strong>{date} - {title}</strong><br/>{text}</li>',
plugins: [
{
xclass: 'Ext.ux.touch.PullRefreshFn',
pullText: 'Henter nyheter',
refreshFn: function () {
Ext.getStore('NewsStore').load();
}
}
]}
The listener on the panel will load the store:
listeners: {
painted: function () {
Ext.getStore('NewsStore').load();
}
}
I have tried to use the callback from the load method. I have tried to get the store from the list and update this, nothing works (the list is simply empty and does not display anything, even though I can see that the code is fetching the information). Any idea what I am doing wrong here?
You have to use setStore property to populate the data
var myStore = Ext.getStore('NewsStore');
Now access the list object and just
mylist.setStore(myStore);

How to dynamically select values in Multiselect combo box - LovCombo ExtJS 3.2

I am using lovcombo in ExtJS 3.2. I fetch the data for initial loading of combo box and I am getting it correctly. But now I have a requirement in which, lets say initially I got 10 entries (options) in combo box, I need to select now 5 options dynamically. Actually I am using it to show dependent entity mapping. Means one entity is dependent on many other entities, so showing them in multiselect combo box. When I get root entity, I need to fetch dependent entities for my root entity, and accordingly I will select those entries dynamically in combo box. This is my code -
{
xtype: 'lovcombo',
fieldLabel: 'data Requirement ',
store: dep_req_store,
displayField: 'text',
valueField: 'value',
mode: 'local',
emptyText: 'Select Requirement...',
triggerAction: 'all',
name: 'data_id',
id: 'data_id' + idSuf,
hiddenName: 'reqIdHid3',
width: 200,
forceSelection: true,
editable: true,
hideOnSelect: false,
beforeBlur: Ext.emptyFn,
}
I will iterate thru each element of this combo after its loaded and will select necessary options:
Ext.getCmp('data_id' + idSuf).getStore().data.items.each(function(record) {
record.dirty = true; //I tried this but no success.
});
Also, I didn't find any attribute which can help me to select the option like:
record.selected = true
So, please help me in this. Is it possible to achieve this using lovcombo?
Thanks in advance.
in record's field definition you can create a new field called checked, this field is by default used by lovcombo to store checked state of the record
fields: [
...
{name: 'checked', type: 'boolean'},
....
]
and when you want to check any record after loading it just do
record.set('checked', true);
Reference:

How to display associated models in separate Ext grids?

I have two associated models, User and Order. A User has many Orders.
Ext.define("User", {
extend: 'Ext.data.Model',
fields: [
'id', 'name'
],
hasMany: {model: 'Order', name: 'orders'},
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
root: 'users'
}
}
});
Ext.define("Order", {
extend: 'Ext.data.Model',
fields: [
'id', 'total'
],
belongsTo: 'User'
});
I'd like to display all of the Users in one grid panel, and all of the orders in another grid. I know how to show all of the Users in a grid, I simply define a store with the User model. But I'm a bit lost as to how to show all of the orders in a separate grid. Do I have to define a separate store? What proxy do I use? Anyone have insight? Basically, I just need a conceptual understanding.
I believe what you are asking for is a fairly common use case. Unfortunately ExtJs is not yet able to cope with this out of the box, simply as currently each grid is bound to a store, but your orders store is created on the fly every time you access it through its user association.
The good news is that you have various ways to achieve this. The best one I can think of is that every time the user clicks on a user row, you get your orders store (user.orders()). Then you can reconfigure your grid with this new store.
Usually each Grid needs its own Store. Showing all orders will work the same way as showing all users, just change the Store ID and it should be okay.

Categories