I'm new to sencha touch and trying to build a list from an array. I use Ext.data.ArrayStore and having trouble.
My code:
var ListStore = new Ext.data.ArrayStore({
autoLoad:myData,
autoDestroy: true,
storeId: 'myStore',
// reader configs
idIndex: 0,
fields: [
'product',
{name: 'product', type: 'string'},
{name: 'id' , type: 'string'}
]
});
Code of the Panel which includes the list:
var listPanel = new Ext.Panel({
dockedItems: [{
xtype: 'toolbar',
ui: 'light',
title: 'Product List',
items: [{
text: 'Back',
ui: 'back',
handler: backHandler
}]
}],
layout: 'fit',
scroll: 'vertical',
style: 'background-color:#FFFFF',
items: [
{
xtype:'list',
store:ListStore,
itemTpl: '<div class="product"><strong>{product}</strong></div>',
grouped:true,
indexBar:true
}]
First of all, Swar's answer seems perfectly correct. Create a store like that, pass your data as the data config option when creating an Ext.data.Store instance.
If you've Ext.define()-ed your own store subclass (without a proxy), you can either add the data when you create() your instance, like this:
Ext.define('MyApp.store.MyStore', {
extends: 'Ext.data.store',
model: 'Demo'
});
myStore = MyApp.store.MyStore({data: arrayOfDemoItems});
Or altertanively, if you already have a store instance (e.g. auto-created by a controller):
Ext.define('MyApp.controller.MyController',{
extend: 'Ext.app.Controller',
stores: ['MyStore'],
init: function () {
// You add your items here
var myStore = this.getMyStoreStore();
myStore.data.addAll(this.getMyItemsSomehow(););
// Note that the 'load' event is not fired if you load elements like this,
// you have to do it manually if you have e.g. a DataView tied to the store:
myStore.fireEvent('load', myStore);
},
getMyItemsSomehow: function () {
// Return an array of items somehow...
return [{id: 1, product: 'Spencer'}];
}
});
Create a Model first.
Ext.regModel('Demo', {
fields: [
{name: 'id', type: 'string'},
{name: 'product', type: 'string'}
]
});
Then create the store:
new Ext.data.Store({
model: 'Demo',
data : [
{id: '1', product: 'Spencer'}
]
});
And as far I can understand from your code, in "autoLoad" option of Store, it should boolean or object which is not the data but options for the store load() method.
Related
I'm new to Sencha Touch...
I've been searching and asking people for hours, but cannot figure out why my detail view does not get the data (using setRecord).
I have not been able to find an example that uses Ext.NavigationView to push a view that uses the data from setRecord, so I suspect I'm doing something wrong there.
I have a tabbed view. First tab shows a list of items. Click an item disclosure to see details for that item. The detail view appears, but with no any data.
The tabs are setup in the launch function of ViewPortController.
The main view in the first tab is the PeopleListView. All the people appear in the list.
The PeopleListView is added to an Ext.NavigationView. A reference to the Ext.NavigationView is added to the PeopleListView so it can be used later
PeopleListViewController has a function, showDetailView, that is successfully called when a disclosure button is tapped.
The controller's showDetailView function
sets the record (which contains the correct data) on the personDetailView,
retrieves the instance of the Ext.NavigationView and pushes the PersonDetailView.
The record value passed to showDetailView has the correct data.
When personDetailView appears, the fields have no data.
ViewPortController:
launch: function() {
// var personDetailView = {
// xtype: 'persondetailview'
// }
var pplView = Ext.create('PeopleApp.view.PeopleListView');
var pplNavView = Ext.create('Ext.NavigationView', {
title: 'People',
iconCls: 'home',
useTitleForBackButtonText: true,
});
pplView.setNavigationView(pplNavView);
pplNavView.add(pplView);
. . .
var mainViewPort = getMainViewPort();
mainViewPort.setItems([pplNavView, . . .]);
},
PersonModel:
Ext.define('PeopleApp.model.PersonModel', {
extend: 'Ext.data.Model',
requires: ['Ext.data.proxy.Rest'],
config: {
idProperty: 'id',
fields: [
{ name: 'id', type: 'auto' },
{ name: 'name', type: 'string' },
{ name: 'address', type: 'string' },
{ name: 'email', type: 'string' },
{ name: 'age', type: 'int' },
{ name: 'gender', type: 'string' },
{ name: 'note', type: 'string' }
],
proxy: {
type: 'rest',
url: '/app/data/people.json',
reader: {
type: 'json',
rootProperty: 'people'
}
},
}
});
PeopleListViewController:
Ext.define('PeopleApp.controller.PeopleListViewController', {
extend: 'Ext.app.Controller',
xtype: 'peoplelistviewcontroller',
config: {
refs: {
peopleListView: 'peoplelistview',
personDetailView: 'persondetailview',
peopleView: 'peopleview',
},
control: {
peopleListView: {
discloseDetail: 'showDetailView'
}
}
},
showDetailView: function(view, record) {
console.log("record.data.name=" + record.data.name);
var detailView = Ext.create('PeopleApp.view.PersonDetailView');
//var detailView = this.getPersonDetailView();
detailView.setRecord(record);
var navView = view.getNavigationView();
navView.push(detailView);
},
launch: function() { this.callParent(arguments); },
init: function() { this.callParent(arguments); },
});
PersonDetailView:
Ext.define('PeopleApp.view.PersonDetailView', {
extend: 'PeopleApp.view.BaseView',
xtype: 'persondetailview',
requires: [
'Ext.form.FieldSet',
'Ext.form.Text',
'Ext.form.TextArea'
],
config: {
title: "Person Details",
scrollable: true,
items: [{
xtype: 'fieldset',
items: [{
xtype: 'textfield',
name: 'name',
label: 'Name: ',
required: true
}, {
xtype: 'textfield',
name: 'age',
label: 'Age: ',
required: false
}, // etc.
]}
]}
});
Can you tell me why detailView.setRecord(record) does not get the data set in the fields of DetailViewController, and what I need to do differently?
I am not sure but you should use below code in your Person detail view:
items: [
{
xtype:'formpanel',
id:'personDetailViewForm',
items:[{
xtype: 'fieldset',
items: [{
xtype: 'textfield',
name: 'name',
label: 'Name: ',
required: true
}, {
xtype: 'textfield',
name: 'age',
label: 'Age: ',
required: false
}, // etc.
]
}]
}]
and in the personListViewController you can set that form's values instead of setting records to the view like:
var detailView = Ext.create('PeopleApp.view.PersonDetailView');
var personDetailViewForm = detailView.down('#personDetailViewForm ');
personDetailViewForm .setValues(records);
Note that records object property names and form fields names must match and if records doesn't work try with records.data.
I am trying to fetch data from store.and i want to use it on my table layout in an extjs panel but always get an empty string though the data is printed in the console. Any pointers would be much appreciated.
<code>
Ext.onReady(function(){
Ext.define('Account', {
extend: 'Ext.data.Model',
fields: [
'id',
'name',
'nooflicenses'
]
});
var store = Ext.create('Ext.data.Store', {
model: 'Account',
autoSync: true,
proxy: {
type: 'ajax',
api: {
read: "accounts"
},
reader: {
type: 'json',
root: 'Account',
successProperty: 'success',
messageProperty: 'message',
totalProperty: 'results',
idProperty: 'id'
},
listeners: {
exception: function(proxy, type, action, o, result, records) {
if (type = 'remote') {
Ext.Msg.alert("Could not ");
} else if (type = 'response') {
Ext.Msg.alert("Could not " + action, "Server's response could not be decoded");
} else {
Ext.Msg.alert("Store sync failed", "Unknown error");}
}
}//end of listeners
}//end of proxy
});
store.load();
store.on('load', function(store, records) {
for (var i = 0; i < records.length; i++) {
console.log(store.data.items[0].data['name']); //data printed successfully here
console.log(store.getProxy().getReader().rawData);
console.log(store);
};
});
function syncStore(rowEditing, changes, r, rowIndex) {
store.save();
}
var rowEditing = Ext.create('Ext.grid.plugin.RowEditing', {
clicksToMoveEditor: 1,
autoCancel: false,
saveText: 'Save',
listeners: {
afteredit: syncStore
}
});
var grid = Ext.create('Ext.panel.Panel', {
title: 'Table Layout',
width: 500,
height:'30%',
store: store,
layout: {
type: 'table',
// The total column count must be specified here
columns: 2,
tableAttrs: {
style: {
width: '100%',
height:'100%'
}
},
tdAttrs: {
style: {
height:'10%'
}
}
},
defaults: {
// applied to each contained panel
bodyStyle:'border:0px;',
xtype:'displayfield',
labelWidth: 120
},
items: [{
fieldLabel: 'My Field1',
name :'nooflicenses',
value: store //How to get the data here
//bodyStyle:'background-color:red;'
},{
fieldLabel: 'My Field',
name:'name',
value:'name'
}],
renderTo: document.getElementById("grid1")
});
});
</code>
Ext.grid.Panel control is totally configurable so it allows to hide different parts of the grid. In our case the way to hide a headers is adding property: hideHeaders:
Ext.create("Ext.grid.Panel", {
hideHeaders: true,
columns: [ ... ],
... other options ...
});
If you still would like to adopt another solution, the more complex solution I have think about is the use of XTemplate for building table dynamically. (http://docs.sencha.com/ext-js/4-1/#!/api/Ext.XTemplate). In this approach you write the template describing how the table will be built.
Otherwise, I still recommend you to deal with the former solution rather than the latter one. The latter approach opposes the basic idea of Sencha ExtJS: use ExtJS library's widgets, customize them in the most flexible way and then automate them by creating store and model.
The most "native" way to show data is by use Ext.grid.Panel.
Example:
Ext.application({
name: 'LearnExample',
launch: function() {
//Create Store
Ext.create ('Ext.data.Store', {
storeId: 'example1',
fields: ['name','email'],
autoLoad: true,
data: [
{name: 'Ed', email: 'ed#sencha.com'},
{name: 'Tommy', email: 'tommy#sencha.com'}
]
});
Ext.create ('Ext.grid.Panel', {
title: 'example1',
store: Ext.data.StoreManager.lookup('example1'),
columns: [
{header: 'Name', dataIndex: 'name', flex: 1},
{header: 'Email', dataIndex: 'email', flex: 1}
],
renderTo: Ext.getBody()
});
}
});
The grid can be configured in the way it mostly customized for user's needs.
If you have a specific reason why to use Ext.panel.Panel with a table layout, you can use XTemplate, but it more complicate to bind the data.
my bbox config :
{
xtype: 'combobox',
editable: false,
store: 'my.store',
displayField: 'name',
valueField: 'id',
name: 'rule',
fieldLabel: 'Rule',
allowBlank: true
}
my model:
Ext.define('rule', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{name: 'id', type: 'int'},
name,
{name: 'json', type: 'string'},
{name: 'json2', type: 'string'}
]
});
my store:
Ext.define('Et.store.odinkod.Rules', {
extend: 'Ext.data.Store',
pageSize: 50,
proxy: {
headers: {'hash': 'hashnumber1'},
type: 'rest',
url: 'api/rule',
reader: {type: 'json', root: 'data'},
writer: {type: 'json', root: 'data'}
},
/*
listeners: {
load: function() {
if(count == 0){
count++;
var instance = Ext.create('Et.model.rule', {
id: '',
accountHash: '',
name: 'Always',
json: '',
uiJson: '',
comment: ''
});
this.add(instance);
}
}
},
*/
autoLoad: true,
autoSync: true,
model: 'rule'
});
so i want to see additional "name" field in the dpopbox without making new record
i can solve my problem if i do "add" method at the store. but thats bad way for me
You cannot use the normal way to add the new item to the store. It will sync with the DB because of your configs autoLoad: true, autoSync: true to the store.
You still can achieve your goal by directly handle the Element of the dropbox, even with the DOM of the dropbox (try Component.getEl().dom). However it is just work-around and is not recommended because the store may fire errors when loading/syncing and/or you will get the data duplicated when the dropbox re-render itself after any actions cause store load.
I'm starting to use sencha touch. I've been able to create a nestedlist layout where clicking on a leaf element triggers a getdetailcard. Now I want to do something that's kind of the reverse of that.
I want to now create a home page with nothing on it but a logo. WHen user clicks on logo, the layout scrolls to a nested list of items.
can someone point me to the relevant documentation or show me sample code?
Thanks
You need to add panel card to your viewport and then on logo tap change the active item.
Here is sample code:
var data = {
text: 'Groceries',
items: [{
text: 'Drinks',
items: [{
text: 'Water',
items: [{
text: 'Sparkling',
leaf: true
}]
}]
}]
};
Ext.regModel('ListItem', {
fields: [{name: 'text', type: 'string'}]
});
var store = new Ext.data.TreeStore({
model: 'ListItem',
root: data,
proxy: {
type: 'ajax',
reader: {
type: 'tree',
root: 'items'
}
}
});
var nestedList = new Ext.NestedList({
title: 'Groceries',
displayField: 'text',
store: store
});
var MyApp = new Ext.Application({
name: 'MyApp',
launch: function() {
MyApp.views.viewport = new Ext.Panel({
fullscreen: true,
layout: 'card',
cardAnimation: 'slide',
items: [
{
xtype: 'panel',
html:'<img src="https://www.google.com/intl/en_com/images/srpr/logo3w.png">',
listeners:{
el:{tap:function(){MyApp.views.viewport.setActiveItem(1,{type:'slide',direction:'left'});}}
}
},
nestedList
]
});
}
});
Just wondering is there a way to handle that in Sencha Touch.
One store and after applying different filters, the store can be used for different places.
For example:
I have a store:
Ext.regModel('abc', {
fields: [{name: 'tid', type: 'int'}, {name: 'name', type: 'string'}, {name: 'parent', type: 'int'}]
});
var store = new Ext.data.Store({
model: 'abc',
proxy: {
type: 'ajax',
url : 'read.php',
reader: {
type: 'json',
root: 'items',
fields: ['tid', 'name', 'parent']
}
},
autoLoad: true,
});
And in a FormPanel, it has two selectfields:
items: [
{
xtype: 'selectfield',
name : 'One',
label: 'Category',
// store: store, <-- Load the whole store
store: function(){
store.filter('name', 'digital'); <-- Load part of store
},
displayField: 'name',
valueField: 'tid'
},{
xtype: 'selectfield',
name : 'Two',
label: 'subCategory',
// store: store, <-- Load the whole store
store: function(){
store.filter('parent', 1); <-- Load part of store
},
displayField: 'name',
valueField: 'tid'
},{
...}
]
Afraid not, You need two instances of your store.
Why not extend your store, just to make it pre-configured like this:
Ext.regModel('abc', {
fields: [{name: 'tid', type: 'int'}, {name: 'name', type: 'string'}, {name: 'parent', type: 'int'}]});
MyStore = Ext.extend(Ext.data.Store, {
constructor: function(config) {
config = Ext.apply({
model: 'abc',
proxy: {
type: 'ajax',
url : 'read.php',
reader: {
type: 'json',
root: 'items',
fields: ['tid', 'name', 'parent']
}
},
autoLoad: true,
}, config);
MyStore.superclass.constructor.call(this, config);
}
})
Then you can use multiple instances of your store and filter them how you want:
items: [
{
xtype: 'selectfield',
name : 'One',
label: 'Category',
store: new MyStore(), //1st instance of MyStore
displayField: 'name',
valueField: 'tid',
listeners : {
'render' : function(){
this.store.filter('name', 'digital');
}
}
},{
xtype: 'selectfield',
name : 'Two',
label: 'subCategory',
store: new MyStore(), //2nd instance of MyStore
displayField: 'name',
valueField: 'tid',
listeners : {
'render' : function(){
this.store.filter('parent', 1);;
}
}
},{
...}
]