ST2: Using 2 unique instances of a store & MVC - sencha-touch

I have a simple test app where I have a carousel that will instantiate multiple of the same type of grid, each grid having it's own copy of a store.
Carousel:
Ext.define('App.view.TopPageCarousel', {
extend: 'Ext.Carousel',
xtype : 'app-toppagecarousel',
requires: ['Ext.Carousel', 'App.view.TopPageGrid'],
config: {
title: 'Top Pages',
items: [{
xtype : 'app-toppagegrid',
title : 'titleA'
},{
xtype : 'app-toppagegrid',
title : 'titleB'
}]
}
});
At first I was defining the store in the grid as a property in its config and I have the controller listening for store changes, just to let me know it was being loaded. The ajax call is made and the grid was populated. However, All grid's were populated with the same data even though unique data was being returned with each call.
Then I found a post that said I needed to instantiate the stores as the grid is being populated, like so:
constructor : function() {
var me = this;
Ext.apply(me, {
store : me.buildStore()
});
me.callParent(arguments);
me.store.load({params : {ufq : this.title}});
},
buildStore : function() {
return Ext.create('App.store.Links');
}
This sort of works. The ajax call is being made, but the grid isn't being populated now and I am not seeing the console.log("Store loaded"); being executed that I placed in the controller. What am I doing wrong?

It turns out in ST2 instead of using Ext.create, the best thing to do is (in my particular instance, not as a standard):
constructor : function() {
this.callParent(arguments);
Ext.setStore('App.store.Links');
},
Using Ext.getStore & Ext.setStore are necessary now if you want a lot of the benefits that go along with events & the store manager.

Related

Extjs4 itemselector, issue in configuration

I try to use itemSelector in extjs4.2 but i don't know i can configure two store. The first multiselect panel is populate by a store, and the second had another too.
I need to save the variation in a DB because the stores that i use is ajax-proxy datastore.
This is my itemselector:
{
xtype: 'itemselector',
id:'itemselector',
name:'userRoles',
anchor:'100%',
store: dsRoles,
toStore: dsUserRoles,
valueField:'id',
displayField:'name',
/*here there is a problem*/
value: dsUserRoles,
msgTarget: 'side',
fromTitle : 'Available',
toTitle : 'Selected'
}
The value in the 'Selected field' is coming from a query and is not static like in the all the example i found.
EDIT: the toStore property doesn't work, and today this component make me crazy: when i load the window which contain a tabPanel which contain the itemselector for the secondTime this is what is render:
Whith Chrome i found this error Uncaught TypeError: Cannot read property 'internalId' of undefined
Any help is helpfull.
Problem has been resolved! I changed the source code!(ItemSelector.js)
here it is,
initComponent: function() {
var me = this;
me.ddGroup = me.id + '-dd';
me.callParent();
// bindStore must be called after the fromField has been created because
// it copies records from our configured Store into the fromField's Store
//me.bindStore(me.store); //don't need to bind
},
createList: function(title, store){ //add a parameter named store
...
store: store, //use the passed store
...
}
...
me.fromField = me.createList(me.fromTitle, me.store);
me.toField = me.createList(me.toTitle, me.toStore);

Pass value to view on create

Im trying to make a custom view and pass a value when I add it in another item using the xtype. It looks simple because I dont need to use stores or anything like that, its just static values but I cant achieve it :(
My idea is to place this in a component (the parent of my custom component):
...
items: [{
xtype: 'myNewComponent',
car: 'Renault'
}]
...
And then in my custom component get the value:
Ext.define('myNewComponent', {
extend: 'Ext.Panel',
xtype: 'myNewComponent',
config: {
items: [{
html: 'This is my car: ' + this.config.car
}]
}
});
I think that Im not understanding something, could you help me?
Thanks!
There are 2 things you need to do.
Firstly, you must create a the new config in your custom component. Doing this is as simple as adding it into the config object of your class:
Ext.define('myNewComponent', {
extend: 'Ext.Panel',
xtype: 'myNewComponent',
config: {
car: null
}
});
null here is merely the default value if you do not change it when you create the component.
Now we want to use this new config. What you have done will not work as the scope of this.config.car is the DOM window. You will need to create the item using a function of your class. You can achieve this by using the new updateCar method of your new car config. This method is called anytime you update that config. In your case, that is when you first create your custom component.
Ext.define('myNewComponent', {
...
updateCar: function(newCar) {
this.add({
html: 'This is my car: ' + newCar
});
}
});
You can find out more about how the config system works here: http://docs.sencha.com/touch/2-1/#!/guide/class_system

Custom xtypes as a cell in ext.listview

I am using sencha touch 2 and not getting help inside sencha forum, so I hope you guys can help me.
I want to create a list with custom items. In this custom item i want to have a horizontal scrollable listview with buttons as items.
I tried to do it component.DataItem but it does no work for me.
I tried also to add an custom xtype als an item in a list, but this does not work.
I think this is a simple task but sencha touch makes it a challenge for me.
So please help me and show me, how can I get a view like shown in this picture.
Instead of a standard list you are going to want to use Component DataView. Essentially, you are going to need to first define an Ext.dataview.component.DataItem, which is then implemented into the DataView. Below is a simple example of a buttons in a DataView as referenced from the DataView guide: http://docs.sencha.com/touch/2-0/#!/guide/dataview
First create the DataItem:
Ext.define('MyApp.view.DataItemButton', {
extend: 'Ext.dataview.component.DataItem',
requires: ['Ext.Button'],
xtype: 'dataitembutton',
config: {
nameButton: true,
dataMap: {
getNameButton: {
setText: 'name'
}
}
},
applyNameButton: function(config) {
return Ext.factory(config, Ext.Button, this.getNameButton());
},
updateNameButton: function(newNameButton, oldNameButton) {
if (oldNameButton) {
this.remove(oldNameButton);
}
if (newNameButton) {
this.add(newNameButton);
}
}
});
We must extend Ext.dataview.component.DataItem for each item. This is an abstract class which handles the record handling for each item.
Below the extend we require Ext.Button. This is simply because we are going to insert a button inside our item component.
We then specify the xtype for this item component.
Inside our config block we define nameButton. This is a custom configuration we add to this component which will be transformed into a button by the class system. We set it to true by default, but this could also be a configuration block. This configuration will automatically generate getters and setters for our nameButton.
Next we define the dataMap. The dataMap is a map between the data of a record and this view. The getNameButton is the getter for the instance you want to update; so in this case we want to get the nameButton configuration of this component. Then inside that block we give it the setter for that instance; in this case being setText and give it the field of the record we are passing. So, once this item component gets a record it will get the nameButton and then call setText with the name value of the record.
Then we define the apply method for our nameButton. The apply method uses Ext.factory to transform the configuration passed into an instance of Ext.Button. That instance is then returned, which will then cause updateNameButton to be called. The updateNameButton method simply removes the old nameButton instance if it exists, and adds the new nameButton instance if it exists.
Now create the DataView:
Ext.create('Ext.DataView', {
fullscreen: true,
store: {
fields: ['name', 'age'],
data: [
{name: 'Jamie Avins', age: 100},
{name: 'Rob Dougan', age: 21},
{name: 'Tommy Maintz', age: 24},
{name: 'Jacky Nguyen', age: 24},
{name: 'Ed Spencer', age: 26}
]
},
useComponents: true,
defaultType: 'dataitembutton'
});
In your case, rather than using a button for the DataItem, you'll want to use a horizontal scrolling list. Here is an example that I found from this answer: Horizontal scrolling list
var list = Ext.create('Ext.DataView',{
store: store,
itemTpl: new Ext.XTemplate('<img src="{icon}" />'),
inline: { wrap: false },
scrollable: {
direction: 'horizontal',
directionLock: true
}
});
Note that you will probably have to use components in the second dataview as well in order to achieve your buttons with image

Extjs4 - Reloading store inside itemselector

I have an itemselecor inside a grid, and i have an combobox that should reload only the store inside the itemselector( the value fields should remain intact)
Here is the itemselector
var grid = Ext.widget('form', {
id: 'grid',
title: '',
width: 600,
bodyPadding: 10,
renderTo: 'itemselectorproduto',
items: [{
xtype: 'itemselector',
name: 'itemselector',
id: 'itemsel',
anchor: '100%',
imagePath: '/ux/images/',
store: store,
displayField: 'Nome',
valueField: 'ID',
value: vitrine,
allowBlank: true,
msgTarget: 'side'
}]
});
I tried to call the normal store.load(), but it have no effect and it shows no error on the console
If needed i will post more of the code, but i think just this should be enough
Thanks,
Looking through the code if ItemSelector it doesn't look like it supports any changes in the store once it's been binded. It basically creates local copies of the data. And if you call bindStore method to assign different store - it will erase your selection.
You can always improve code in ItemSelector to allow such behavior. It should not be a problem. You can subscribe to datachanged or load event of the store when binding to it, and then handle situation when store data is changed.
Actually i think the best way to do such thing is using ItemSelector`s "populateFromStore". Sure except of extending item selector. In case of extending you should look on the "onBindStore" function of the ItemSelector.
onBindStore: function(store, initial) {
var me = this;
if (me.fromField) {
me.fromField.store.removeAll()
me.toField.store.removeAll();
// Add everything to the from field as soon as the Store is loaded
if (store.getCount()) {
me.populateFromStore(store);
} else {
me.store.on('load', me.populateFromStore, me);
}
}
}
So as you see in case of the empty store it hooks to the load event. And it should be like this:
onBindStore: function(store, initial) {
var me = this;
if (me.fromField) {
me.fromField.store.removeAll()
me.toField.store.removeAll();
me.store.on('load', me.populateFromStore, me);
// Add everything to the from field as soon as the Store is loaded
if (store.getCount()) {
me.populateFromStore(store);
}
}
}

update a nested list in sencha touch 2

I'm having trouble redrawing my nested list with sencha touch 2. My code looks something like the following;
var data = {items:[{text:'hello', leaf:true}]};
Ext.application({
name:'main',
launch:function(){
Ext.define('ListItem', {
extend: 'Ext.data.Model',
config: {
fields: ['text']
}
});
var treeStore = Ext.create('Ext.data.TreeStore', {
id: 'mystore',
model: 'ListItem',
defaultRootProperty: 'items',
root: data});
Ext.create('Ext.NestedList', {
id:'mylist',
fullscreen: true,
store: treeStore
});
} // end launch:function()
}); // end Ext.application
During run time, I modify the data variable like so data.items[0].text = 'bye'. How do I get the nestedlist to refresh and show bye? I tried the following but none of them work:
var mystore = Ext.data.StoreManager.lookup('mystore');
mystore.setRoot(data);
Ext.getCmp('mylist').refresh(); // refresh, update, dolayout, repaint etc... does not exist.
Ext.getCmp('mylist').bindstore(mystore); // bindstore is deprecated
you should change data through record/store instances only then the Ext.NestedList will be automatically updated
var record = treeStore.getAt(0);
record.set('text', 'bye');
Working with data within a store is to be done using getById() and getAt(), which return Models that implement NodeInterface. Add data via appendChild, and the rest is self explanatory from there. The id value can be overridden in your data to make navigating the tree easier.
getStore().getById('myFirstLevelId').getById('mySecondLevelId').getById('myThirdLevelId')
http://docs.sencha.com/touch/2-0/#!/api/Ext.data.NodeInterface