Saving Model with hasOne association - sencha-touch-2

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

Related

Sencha Touch synch not saving to proxy

I have a piece of code in a Sencha Touch v2 controller as shown below. When this code is ran the count after the store.add is (6), the counter after the store.sync is (0) and the store.sync is succeeding.
NOTE: items holds 6 records received from a JsonP proxy, no errors are shown in the console and everything acts as though it was a full success.
requires: [
'Ext.data.proxy.JsonP',
'Ext.data.proxy.Sql'
],
config: {
models: ['Convention'],
stores: ['Conventions']
},
// ***additional code*** //
store.setProxy({
type: 'sql',
database: 'app',
table: 'Conventions'
});
store.removeAll();
store.sync({
success: function(batch){
store.add(items);
console.log("Count before: " + store.getCount()); << Shows (6)
store.sync({
failure: function (batch, options) {
console.log('Convention Sql failure');
},
success: function(batch,options){
console.log("Count after: " + store.getCount()); << Shows (0)
console.log("Convention Sql success");
store.load();
Ext.Viewport.unmask();
}
});
}
});
The model is show here
extend: 'Ext.data.Model',
config: {
idProperty: 'id',
fields: [
{ name: 'id', type: 'string' },
{ name: 'name', type: 'string' },
{ name: 'logoId', type: 'string' },
{ name: 'seasonId', type: 'string'},
{ name: 'viewed', type: 'string'},
{ name: 'dateCreated', type: 'string'},
{ name: 'dateUpdated', type: 'string'}
]
}
and the store is here
extend: 'Ext.data.Store',
requires: [
'Ext.data.proxy.Sql'
],
config: {
model: 'app.model.Convention',
autoLoad: false,
sorters:[{
property: 'name',
direction: 'ASC'
}],
proxy: {
type: 'sql',
database: 'app',
table: 'Conventions'
}
}
After much research it seems that Sencha recently changed some of their code on how they handle IDs. As such, if you are using code examples previous to this change you will get errors when you try to save to the ID field.
Sencha has added the clientIdProperty that you can add to the writer of a proxy and directly to the model.
Reference: http://docs.sencha.com/touch/2.4/2.4.2-apidocs/#!/api/Ext.data.Model-cfg-clientIdProperty
The name of a property that is used for submitting this Model's unique client-side identifier to the server when multiple phantom records are saved as part of the same Operation. In such a case, the server response should include the client id for each record so that the server response data can be used to update the client-side records if necessary. This property cannot have the same name as any of this Model's fields.
As such, my code above will have the following changes to the following where 'siteId' is my id being passed from the Json request and the ID on my server for the record.
model
idProperty: 'id',
clientIdProperty: 'siteId',
identifier: 'uuid',
Controller
store.setProxy({
type: 'sql',
database: 'app',
table: 'Conventions',
writer: {
clientIdProperty: 'siteId'
}
});

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.

How to set dynamic url in sencha touch using store?

I am new for this platform, Now i am unable to set dyanimic url using category id and token.
What i want:
I have list different items, which have different ids but same token, token(tokent is same one user) getting from login phase. I want to get value accorading to category id from the server.
Here is the my model:
Ext.define('MyApp.model.CategoryDisplayModelMenu', {
extend: 'Ext.data.Model',
config: {
fields: [
/*'cat_id',*/
'category',
'name',
],
belongsTo: "MyApp.model.CategoryDisplayModel"
}
});
and another related model is:
Ext.define('MyApp.model.CategoryDisplayModel', {
extend: 'Ext.data.Model',
requires: ['MyApp.model.CategoryDisplayModelMenu'],
config: {
fields: [
{name:'data', mapping: 'data'},
{name:'name'},
{name: 'category'},
{name: 'author'},
],
}
});
What i am set in store, but could not work:
Ext.define('MyApp.store.CategoryValueStore', {
extend: 'Ext.data.Store',
alias: 'store.CategoryValueStore',
requires: [
'MyApp.model.CategoryDisplayModel'
],
config: {
model: 'MyApp.model.CategoryDisplayModel',
storeId: 'categoriesvaluestore',
proxy: {
type: 'rest',
url: 'http://horror/myapp/api/word/searched_words/catID/'+ 1+'/'+ SDSILLYTOKEN+'/'+650773253e7f157a93c53d47a866204dedc7c363,
noCache: false,
reader: {
type: 'json',
rootProperty: ''
} } }
});
How to set above url, dynamic, cat id and token may be differnt.
But it works when i set these in store
Ext.define('MyApp.store.ArchitectureDisplayStore',{
extend: 'Ext.data.Store',
requires:[
'MyApp.view.Main'
],
config:
{
model: 'MyApp.model.CategoryDisplayModel',
autoLoad:true,
id:'Category',
proxy:
{
type: 'ajax',
url : 'http://horror/myapp/api/word/searched_words/catID/1/SDSILLYTOKEN/650773253e7f157a93c53d47a866204dedc7c363', // file containing json data
reader:
{
rootProperty:''
} } }
});
In View , I set getting value on list like this:
Ext.define("MyApp.view.ArchitectureDisplayMain", {
extend: 'Ext.Container',
alias: "widget.architecturewords",
config: {
{
xtype: 'list',
scrollable: true,
itemId: 'demolist',
itemTpl: [
'<div><tpl for="data"><ul class="catList">{name} -test- {category}</ul> <ul>{author}</ul></tpl></div>'
],
store: 'categoriesvaluestore',
}
}
});
My category display model:
Ext.define('MyApp.model.CategoryModelMenu', {
extend: 'Ext.data.Model',
config: {
fields: [
'cat_id',
'category_name',
],
belongsTo: "MyApp.model.CategoryModel"
}
});
and
Ext.define('MyApp.model.CategoryModel', {
extend: 'Ext.data.Model',
requires: ['MyApp.model.CategoryModelMenu'],
config: {
fields: [
{name:'data', mapping: 'data'},
{name: 'cat_id'},
{name: 'category_name'},
],
}
});
EDIT:
Ext.define('MyApp.view.Category', {
extend: 'Ext.List',
alias: "widget.category",
config: {
title: 'Stores',
cls: 'category-data',
scrollable: false,
store: 'CategoryStore',
itemTpl: [
'<div class="categoryListings">',
'<tpl for="data">',
'<span onClick="catOption({cat_id})">{category_name}</span> ',
'</tpl>',
'</div>',
].join('')
}
//}
});
function catOption(id){
console.log("ID--"+id);
var tokan= '650773253e7f157a93c53d47a866204dedc7c363';
Ext.Viewport.remove(Ext.Viewport.getActiveItem(), true);
Ext.Viewport.add([
{ xtype: 'wordsview' }
]);
} and others
In wordsview, I like to display respective words of clicked category.
It is ok, when click this, first item of id p1, it shows next view.
Please tell me, How to get dynamic data accorading to its category id and token. please give some solution.Thank you advance.
If i understood you correctly
Let's say if you have category id and token in localStorage.
You can do like this
proxy:
{
type: 'ajax',
url : 'http://horror/myapp/api/word/searched_words/catID/'+localStorage.catId+'/SDSILLYTOKEN/'+localStorage.token,
reader:{
rootProperty:''
}
}
OR
Do as #Alex posted. That is better way.. Like
function catOption(id){
console.log("ID--"+id);
var token= '650773253e7f157a93c53d47a866204dedc7c363';
var url = 'http://horror/myapp/api/word/searched_words/catID/'+id+'/SDSILLYTOKEN/'+token;
Ext.getStore("categoriesvaluestore").getProxy().setUrl(url);
Ext.getStore("categoriesvaluestore").load();
Ext.Viewport.remove(Ext.Viewport.getActiveItem(), true);
Ext.Viewport.add({ xtype: 'wordsview' });
}
When accessing your Store from your View or anywhere else, you can dinamically change the Url this way:
var stProxy = Ext.StoreMgr.get("myStore").getProxy();
stProxy.setUrl("http://the.new.url");
Ext.StoreMgr.set("myStore").setProxy(stProxy);
--
The particular problem in your scenario is that you may have to populate your list manually. If you want a List to include the result of calling the same Store with different URLs, I suggest to build a new local Store loading the content of all iterations. Then make the List "store" property be this global Store.

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()

Sencha Touch 2 read tree structure from json

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.