PDA

View Full Version : Store and select box



ozTemplar
20 Jun 2010, 11:03 PM
First of all, great work guys! Love the demos and now trying to create some simple apps.

In Extjs, I've been able to define a store to use for select boxes (ComboBox UI) like so:


comboStore = new Ext.data.SimpleStore({
fields: ['category_id', 'category', 'default_flag'],
data : categories
});

combo = new Ext.form.ComboBox({
store: comboStore,
displayField:'category',
transform: 'category',
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText:'Select a category...',
...


When I try something similar for the Select UI in Sencha Touch:


var sitesModel = Ext.regModel( 'Sites', {
fields: [
{name: 'category_id'},
{name: 'category'}
]
});
var categories = [ [0,'-'],
[5,'NACA'],
[59,'Food'],
[11,'Programs'],
[58,'Sports']
];
//
var comboStore = new Ext.data.Store({
reader: new Ext.data.ArrayReader (
{
idProperty: 'category_id'
}
),
model: 'Sites'
//,data : categories
});

//comboStore.loadData(categories);
combo = new Ext.form.Select({
store: comboStore,
displayField:'category',
transform: 'category',
typeAhead: true,
mode: 'local',
triggerAction: 'all',
emptyText:'Select a category...',
selectOnFocus:true,
valueField: 'category_id',
value: currCategoryId
});

it always bring up an error "this.model is udefined". I've just followed what was in the documentation. Am I missing something?

ozTemplar
21 Jun 2010, 9:48 PM
no-one has answered this yet :(. so, just a quick question then: is it even possible for the Select component to get data from a store? i need it so to dynamically assign options to the select box(es).

TommyMaintz
22 Jun 2010, 1:43 PM
Sorry for the delay. The Select component is not a one on one copy from the Combobox. You pass it an options array containing objects with value and text properties at instantiation time. You could load a store and pass the store.data object to the options of the Select as soon as the store is loaded. You can change the valueField and displayField properties on the Select to use custom fields in your model.

Having said that, it seems like the error you are getting is related to your store definition. Could you try to remove your reader definition and see if you still get the error?

I think since you are using an ArrayReader and you have your data defined in code, you should skip the step of creating a store altogether and it would be easier to just do something like



new Ext.form.Select({
options: [{
key: 0,
value: '-',
}, {....}
});

ozTemplar
24 Jun 2010, 1:35 PM
Thanks tommy!

I'll try your suggestion. The real reason behind the Store-way of doing things is that the backend code already provides the store's data in JSON format. If there's no other way around it, the backend can spit out differently, I suppose.

But the main objective is to create linked select boxes. When the parent select box changes value (onSelect), the secondary one changes options as well. I then need to have a way to dynamically change the child options. Before, I was able to attach a listener to the 'select' event of the parent ComboBox and somewhere i do 'secondaryCombo.store.filter()'.

Are there any example in the wiki or anywhere of linked select boxes? I've searched to no avail. :s

TommyMaintz
24 Jun 2010, 1:38 PM
There is no example for this yet. We are aiming to improve the way you deal with forms drastically in the 1.0 release and will definitely look at this thread to see how we can make what you are trying to do easier.

ozTemplar
28 Jun 2010, 7:09 PM
I've followed your suggestion to load a Store and pass the store.data object to the options of the Select. After much twidling, this is what I've got so far:




Ext.regModel('sourceVideo', {
fields: [
{name:"video_id", type: 'int'},
{name:"video_title", type:'string'}
]
});
var myStore = new Ext.data.JsonStore({
id: 'video-store',
model:Ext.ModelMgr.types['sourceVideo']
});

Ext.util.JSONP.request({
url: '/mobile/json-video',
callbackKey: 'callback',
callback: function(data) {
videos = data.results;
myStore.loadData(videos);
vcombo.options = myStore.data;
}
});

var vcombo = new Ext.form.Select({
name: 'myCombo',
label: 'Videos',
typeAhead: true,
emptyText:'Select a Video',
selectOnFocus:true,
id:'selectVideo',
displayField:'video_title',
valueField:'video_id',
//store: myStore,
options: myStore.data
});

var formBase = {
scroll: 'vertical',

items: [
{
xtype: 'fieldset',
title: 'Test Forms',
instructions: 'Please select above',
defaults: {
required: true,
labelAlign: 'left'
},
items: [
vcombo,
{
xtype: 'select',
// blah
}
]
}
]
// ... blah



I've chosen to use JSONP.request as I've tried AjaxProxy and it didn't load the data. Also, I can't seem to check the proxy's onsuccess event.

Anyways, the above code still seems to fail. The select box isn't populating, even though I could trace that the JSON objects have been loaded into the Store. How do you exactly pass the data into the options of the select? How does one 'refresh' that data to make the select box render with the latest information from the JSON request? Been wracking my brains over this... again, there were ways from Extjs, but hasn't seem to have been ported to Sencha Touch.

tobinharris
4 Jul 2010, 10:23 AM
Bump on this one.

I'm wondering if it would be easier to break away from the Component model and just use regular jQuery-style DOM mashing?

T

TommyMaintz
6 Jul 2010, 12:54 PM
You could do that. Our select box basically is a very simple wrapper around an HTML select element. We just need to add support for dynamically updating the options, and maybe binding a store to it to load the options. Both are very simple to implement and shouldn't add too much complexity to the component.

tobinharris
9 Jul 2010, 10:53 AM
Thanks. You're right, it was pretty straight forward.



//a select box that can be updated really easily
// E.g
// var s = Ext.getCmp('my-select-box')
// s.updateOptions([{text: '1', value: 'one'}])
Ext.form.DataBoundSelect = Ext.extend(Ext.form.Select, {
//updates the options
//only tested in Safari web browser and iPhone/iPad emulator
updateOptions: function(newData){
var select = Ext.getCmp(this.id);

//clear out old ones
all = select.getEl().select('option');
all.remove();
//add in the new
for(var i = 0; i<newData.length;i++){
console.log(select.el.child('select'))
select.el.child('select').createChild({tag: 'option', value: newData[i].value, html: newData[i].text});
}
}
});
//let us use ths as an xtype in other place
Ext.reg('databound-select', Ext.form.DataBoundSelect);

TommyMaintz
13 Jul 2010, 11:54 AM
Nice solution. Our implementation will be similar except that it will also be able to be bound to a store. It could listen for the datachanged event and call a function similar to your updateOptions.

krause
26 May 2011, 9:06 AM
And when is your solution going to be available? If it is already in place how is it used. I'm also struggling to make a Select widget work with a Store, but so far had to do it manually (i.e. load the store, listen to the load event, fill in the Select's options).

Riaz
29 May 2011, 9:04 PM
I am also facing same problem. Is it possible now?

Riaz
29 May 2011, 9:06 PM
Krause,

Could you give me any sample code. I can not forward.

krause
30 May 2011, 8:46 AM
The field:


{
xtype : 'selectfield',
name : 'sampleSelectField',
label : 'Sample',
displayField : 'name',
valueField : 'id'
// store : store <---- This doesn't work
}

The store:



var store = new Ext.data.Store( {
fields : [ {
name : 'id',
type : 'int'
}, {
name : 'name',
type : 'string'
}],
proxy : {
type : 'ajax',
url : "http://x.x.x.x/rest/entity",
reader : {
type : 'json',
root : 'list'
}
},
listeners : {
load : function(store, recs, success) {
// I search for my Select field and manually fill it:
var selectField = container.query(".selectfield[name='sampleSelectField]")[0];
selectField.setOptions(recs);
}
}
});


In order to load the store you have to do it programatically beforehand. I didn't find any event that would be called when the select gets triggered by the user so you have to fill it upfront (not very ajaxy...):



store.load( {
params : {
myParam : someField.getValue()
}
});

krause
30 May 2011, 3:42 PM
With this override to Ext.form.Select it works as expected (by me at least). Please note that this is an untested quick hack that I made while exploring and trying to understand the inner workings of the component. I hope I'm wrong and there actually is already a way to do this without the hacking. I would hate to see the parade of user extensions in the forum as it is for ExtJS.


Ext.override(Ext.form.Select, {

originalInitComponent : Ext.form.Select.prototype.initComponent,

// @private
initComponent: function() {
var me = this;

if (this.store) {
this.store.on('load', function() {
me.originalShowComponent();
});
}
Ext.form.Select.prototype.originalInitComponent.call(this);
},

originalShowComponent : Ext.form.Select.prototype.showComponent,

// @private
showComponent: function() {
this.store.load();
}
});

What I'm doing here is overriding the showComponent function wich shows the list of options and instead I'm firing the store's load method. When the store gets loaded, and only then, I show the list of options for the user to select. This would still need an indicator that the data is loading. You may add a 'beforeload' listener to your store to pass in any required parameters to the ajax call (e.g. if the select depends on the value of another select or field).


var store = new Ext.data.Store( {
. . .
listeners : {
beforeload : function(store, operation) {
operation.params = {
myParam : anotherField.getValue()
}
}
}
});

Riaz
30 May 2011, 4:16 PM
The field:


{
xtype : 'selectfield',
name : 'sampleSelectField',
label : 'Sample',
displayField : 'name',
valueField : 'id'
// store : store <---- This doesn't work
}

The store:



var store = new Ext.data.Store( {
fields : [ {
name : 'id',
type : 'int'
}, {
name : 'name',
type : 'string'
}],
proxy : {
type : 'ajax',
url : "http://x.x.x.x/rest/entity",
reader : {
type : 'json',
root : 'list'
}
},
listeners : {
load : function(store, recs, success) {
// I search for my Select field and manually fill it:
var selectField = container.query(".selectfield[name='sampleSelectField]")[0];
selectField.setOptions(recs);
}
}
});


In order to load the store you have to do it programatically beforehand. I didn't find any event that would be called when the select gets triggered by the user so you have to fill it upfront (not very ajaxy...):



store.load( {
params : {
myParam : someField.getValue()
}
});


Thanks for sharing your code.
I need some clarify on based of your code. How can I reload the 'store' object? I want to upload the 'store' object when I tap s'electField'. Is it possible?

lakilevi
13 Oct 2011, 4:37 AM
Thanks for sharing!!!

I hope Sencha will offer a native solutions for this soon.

Ades
5 Feb 2013, 3:32 AM
Is there now a solution for Selectfield and update a store?