Sencha Touch 2 read tree structure from json - sencha-touch-2

I'm trying to figure out how to read a tree structure like this into proper model instances:
{
"name":"root"
"kids":[
{
"name":"kid1",
"kids": [...] //More kids
},
{
"name":"kid2",
"kids": [...] //More kids
},
{
"name":"kid3",
"kids": []
},
...
]
}
Here are two of the models I've tried:
Ext.define('TreeNode', {
extend: 'Ext.data.Model',
config: {
fields: ['name'],
hasMany:{model: 'TreeNode', name: 'kids'}
}
});
//This one seems to work, but it simply loads
//generic objects into the "kids" property
//and not real model instances.
Ext.define('TreeNode', {
extend: 'Ext.data.Model',
config: {
fields: ['name', 'kids']
}
});
And the store:
Ext.define('TreeStructureStore', {
extend: 'Ext.data.Store',
config: {
autoLoad: false,
model: 'TreeNode',
proxy: {
type: 'ajax',
url: 'simple.json',
reader: {
type: 'json'
}
}
}
});
I cannot seem to get the model and store to work correctly. At best it will only read the topmost element. How can I get it to read recursively down and make the correct model instance tree?

http://www.sencha.com/forum/showthread.php?178848-Nested-JSON-and-hasMany-associations
Looks similar to a problem I had and was able to solve eventually (and posted the answer to in the Sencha Forum). The key point here is using the associationKey config property for the hasMany association, but check out the whole post.

Related

Model with associations, 1 request fill 2 components best practice

What would be the best practice or design approach for the following scenario:
There is a json been returned from the server that has information about people and their addresses
I need to show a form with the general information of the person plus a list with every address.
In this list it is mandatory that each address is an item of the list because it will be multiselect true in order to do something else.
What I have done is:
a)define a model "Persona" with a hasMany relation to "Direccion"(spanish for address), my proxy is here in the model
b)define a model "Direccion"
c)define a list and try to play with the itemTpl config in order to display 1 address per itemList but so far I can only display all the addresses for a given person in the same itemList.
Is there a way to achieve this ?
Is this approach good given this scenario?
I was trying to do only 1 request and have only 1 store to fill out this 2 components but now I'm having doubts about it.
So what would be the best design/practice given this scenario?
JSON response
{
"personas": [
{
"id": 1,
"nombre": "jon",
"apellido": "caballero",
"direcciones": [
{
"direccionId": 1,
"calle": "fco villa",
"colonia": "barona"
},
{
"direccionId": 2,
"calle": "duraznos",
"colonia": "canutillo"
}
]
}
]
}
Models
Ext.define('Associations.model.Direccion', {
extend: 'Ext.data.Model',
config: {
idProperty: 'direccionId',
fields: [
{ name: 'calle', type: 'auto' },
{ name: 'colonia', type: 'auto' }
]
}
});
Ext.define('Associations.model.Persona', {
extend: 'Ext.data.Model',
requires: ['Associations.model.Direccion'],
config: {
fields: [
{ name: 'nombre', type: 'auto' },
{ name: 'apellido', type: 'auto' },
],
hasMany:[
{
foreignKey: 'direccionId',
associationKey: 'direcciones',
name: 'direcciones',
model: 'Associations.model.Direccion'
}
],
proxy: {
type:'ajax',
url: 'data/respuesta.json',
reader: {
type:'json',
rootProperty:'personas'
}
}
}
});
Store
Ext.define('Associations.store.Persona', {
extend: 'Ext.data.Store',
requires: [
'Associations.model.Persona'
],
config: {
model: 'Associations.model.Persona',
autoLoad: true
}
});
List
Ext.define('Associations.view.PersonaList', {
extend: 'Ext.List',
xtype: 'personalist',
config: {
onItemDisclosure: true,
emptyText: 'No se encontraron personas',
store: 'Persona',
padding: 10,
margin: 10,
itemTpl : [
'<tpl for="direcciones">',
'<li>Colonia {colonia}</li>',
'<li>Calle {calle}</li>',
'</tpl>',
].join('')
}
});
Any ideas?
Thanks in advance.
When you do model.load() and the model has a hasMany relation to another model a store for the child objects is autogenerated therefore the best approach would be to load the model get the store of the child records and set it to the list.

Calling data from store in a normal Tab Panel

I'm trying to call 2 values from my store, and set it inside the styles in a div which I put it in a html: item. The store loads the data from a web API, which is working fine(I've tested using fiddler and the return response is correct) but I cant get the data in the store to work inside the html item.
Below is my view:
Ext.define('myapp.view.Main', {
extend: 'Ext.tab.Panel',
requires:['myapp.store.Style'],
items: [
{
id: 'firstpage',
title: 'Welcome',
store: 'styleStore',
styleHtmlContent: true,
scrollable: true,
items: [
{
html: ['<div id="testStr1" style="font-style:{FontStyle}; color:{Color};">',
'This is a test string.',
' Go to the settings to change the style',
'</div>'
].join("")
}
]
},
}
]
}
My Store:
Ext.define('myapp.store.Styles', {
extend: 'Ext.data.Store',
requires:[
'myapp.model.Style'
],
config: {
autoLoad: true,
model: 'myapp.model.Style',
storeId: 'styleStore',
clearOnPageLoad:false,
proxy:
{
type: 'ajax',
listeners: {
exception:{
fn: function(pxy, response, operation, options){console.log("We've got a problem...");}
}
},
url: 'http://localhost/styleapi/api/styles',
reader: {
type: 'json',
rootProperty: 'data',
}
}
}
});
My model:
Ext.define('myapp.model.Style', {
extend: 'Ext.data.Model',
fields:[
{
name: 'Id',
type: 'int'
},
{
name: 'FontStyle'
},
{
name: 'Color'
},
],
proxy: {
type: 'rest',
url: 'http://localhost/styleapi/api/styles'
}
});
A few issues here...
First, your main class, myapp.view.Main, is nesting items inside it, and those items are not configured correctly. Your items: ... should be inside of config, and there should be an xtype for each item, if you want the item to not be the default type of container. In your current code, you have an items: .. config on your first item, where you are putting html. This results in a nested component, which is not what you are intending here.
In addition, you are using html, when you really want to use a template. When you have a fixed set (or object) of data, you can use a component with tpl and data; when using a store for the data, you would use a dataview with an itemTpl config, which will repeat that template for each item in the store. Currently, your top-level item is defaulting to a container, where you are using a store config, which won't do anything at the moment.
So, steps to fix:
Move the top-level item into config property
Change the top-level item to be a dataview
Move the html out of the nested item and into an itemTpl property as an XTemplate (i.e. itemTpl: new Ext.XTemplate('<div ...'))

Adding a AJAX response data to a store

How to add a data to a json store if my data is coming from a back end AJAX call.
my store is as follows .
Ext.define('MyApp.store.GeographyMasterStore', { extend: 'Ext.data.Store',
requires: [
'MyApp.model.GeographyMasterModel'
],
config: {
model: 'MyApp.model.GeographyMasterModel',
storeId: 'geographyMasterStore',
proxy: {
type: 'ajax',
reader: {
type: 'json'
}
}
}
});
And my model is as follows:
Ext.define('MyApp.model.GeographyMasterModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'Code'
},
{
name: 'Description'
},
{
name: 'Level_Code',
mapping: 'Level Code'
},
{
name: 'Name'
}
]
}
});
If I add the data like this
var geographyMasterStore = Ext.getStore('geographyMasterStore');
geographyMasterStore.add(<data from backend AJAX call>);
it does not show me the mapped field i.e. Level_Code
Usually I when add a record to the store like this :
Ext.create('App.model.MyModel', JSON.parse(response.responseText);
Where response is the response from an Ext.Ajax.request
Hope this helps
You need create a model:
var record = Ext.create('model.GeographyMasterModel', Ext.JSON.decode(response.responseText));
save the model:
record.save()
reload the store:
geographyMasterStore.load()

Saving Model with hasOne association

I've got these models :
Ext.define('TestApp.model.User', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'username', type: 'string'},
],
proxy: {
type: 'localstorage',
},
},
});
Ext.define('TestApp.model.Config', {
extend: 'Ext.data.Model',
config: {
hasOne : {model: 'TestApp.model.User', name: 'user'},
proxy: {
type: 'localstorage',
},
}
});
I've tried to save a config entry like this :
var david = Ext.create('TestApp.model.User', {username: 'david'})
david.save();
var config = Ext.create('TestApp.model.Config');
config.setUser(david);
config.save();
When I restart the application, I have my user entry saved and my config entry saved but, my association is not saved:
config.getUser() -> I get undefined
According to Mitchell Simoens storing associated data isn't supported.
Unsure if it helps in your case, but an approach is sketched (that approach also seems to adress my own current (unrelated) problem).
Hope it helps

Nested List not loading in sencha

I am trying to load a Nested list onto my Sencha app. The problem is I am not familiar with it and i am not sure if the json file i am using is correct.
[
{
"text":[
{
"text":"1.1.1",
"leaf":true
}],
"text":[
{
"text":"1.1.1",
"leaf":true
}
]
}
]
This is my store code
//Defining the store for the Nested List
Ext.define('InfoImage.store.nestedListStore', {
extend: 'Ext.data.TreeStore',
requires: 'InfoImage.model.nestedListModel',
id:'nestedListStore',
config:{
//Calling the required model for the Work Item List
model : 'InfoImage.model.nestedListModel',
//Defining the proxy for the Work Item List to pull the data for the List
proxy : {
type : 'ajax',
url : 'app/model/data/list.json',
reader: {
type: 'json',
root: 'items'
}
},
autoLoad: true
}
});
and my main code is
Ext.define("InfoImage.view.nestedList", {
extend:'Ext.NestedList',
xtype:'nestedList',
id:'nestedList',
config:{
fullscreen:'true',
title:'Nested List',
xtype:'nestedList',
//displayField : 'text',
html:'Nested List on its way!!!',
store:'nestedListStore'
//itemTpl:'{text}'
}
});
The output thats displayed is [object object]. I dont know what is missing. ANy help is appreciated.
Firstly, your Json is a VALID json. Always check for valid json by pasting the json on jsonlint.com
Secondly, I see that you have commented out the
displayField:'text'
property. If you don't provide the displayField to the nestedlist, it won't come to know, which items from the data store to show in the list.
Probably, that's why you are getting the [object Object] as your o/p in the list.
Uncomment the above line and check.
It seems that your JSON cannot work with Ext.NestedList because text is a field of your Model and it should not be declared as rootProperty in your JSON file.
Firstly, assume that you have this model definition:
Ext.define('ListItem', {
extend: 'Ext.data.Model',
config: {
fields: ['text']
}
});
According to your data, your JSON file should look like this:
items: [
{
text: '1.1',
items: [
{ text: '1.1.1', leaf: true },
{ text: '1.1.2', leaf: true }
]
}
]
You have to add this config to your Store as well defaultRootProperty: 'items'