EXTJS4--Why don't my associated stores load child data? - extjs

So I have a parent and child store, illustrated here:
Parent Model
Ext.define('APP.model.Client', {
extend: 'Ext.data.Model',
requires: [
'APP.model.Website', 'Ext.data.association.HasMany', 'Ext.data.association.BelongsTo'],
fields: [{
name: 'id',
type: 'string'
}, {
name: 'name',
type: 'string'
}, {
name: 'slug',
type: 'string'
}, {
name: 'active',
type: 'boolean'
}, {
name: 'current',
type: 'boolean'
}],
hasMany: {
model: 'APP.model.Website',
name: 'websites'
}
});
Child Model
Ext.define('APP.model.Website', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'string'
}, {
name: 'client_id',
type: 'string'
}, {
name: 'sub_domain',
type: 'string'
}, {
name: 'active',
type: 'boolean'
}],
belongsTo: 'APP.model.Client'
});
Using an AJAX call via the server, I am loading the Clients store, and that is loading fine. But the Websites store isn't populated, and when I breakpoint on the Clients store on.load function, to see what it's populated with, the Client store is only populated with the client data, but in the raw property for that store, I can see all the websites data. So it's being returned correctly, but my extjs isn't correct. Here are the stores:
Client Store
Ext.define('APP.store.Clients', {
extend: 'Ext.data.Store',
autoLoad: false,
model: 'APP.model.Client',
proxy: {
type: 'ajax',
url: '/client/list',
reader: {
type: 'json',
root: 'items'
}
},
sorters: [{
property: 'name',
direction: 'ASC'
}]
});
Websites Store
Ext.define('APP.store.Websites', {
extend: 'Ext.data.Store',
requires: ['Ext.ux.Msg'],
autoLoad: false,
model: 'APP.model.Website',
proxy: {
type: 'ajax',
url: '/client/list',
reader: {
type: 'json',
root: 'items'
},
writer: {
type: 'json'
}
},
sorters: [{
property: 'sub_domain',
direction: 'ASC'
}]
});
My final result is...I would like to populate both stores so I can click on an element, and when it loads something from the parent store, I can access the child store(s) (there will be more when I figure out this problem) to populate a couple grid(s) in tabs.
What am I missing as far as my setup? I just downloaded extjs4 a couple days ago, so I am on 4.1.

Put your proxies in your models, unless you have a good reason not to [1]
Make sure you require the related model(s), either in the same file, or earlier in the application
Use foreignKey if you want to load the related data at will (i.e. with a later network request).
Use associationKey if the related data is loaded in the same (nested) response
Or just use both
Always name your relationships (otherwise the name will be weird if using namespaces).
Always use the fully qualified model name for the model property in your relationships
Working code:
model/Contact.js:
Ext.define('Assoc.model.Contact', {
extend:'Ext.data.Model',
requires:[
'Assoc.model.PhoneNumber'
],
fields:[
'name' /* automatically has an 'id' field */
],
hasMany:[
{
model:'Assoc.model.PhoneNumber', /*use the fully-qualified name here*/
name:'phoneNumbers',
foreignKey:'contact_id',
associationKey:'phoneNumbers'
}
],
proxy:{
type:'ajax',
url:'assoc/data/contacts.json',
reader:{
type:'json',
root:'data'
}
}
});
model/PhoneNumber.js:
Ext.define('Assoc.model.PhoneNumber', {
extend:'Ext.data.Model',
fields:[
'number',
'contact_id'
],
proxy:{
type:'ajax',
url:'assoc/data/phone-numbers.json',
reader:{
type:'json',
root:'data'
}
}
});
data/contacts.json:
{
"data":[
{
"id":1,
"name":"neil",
"phoneNumbers":[
{
"id":999,
"contact_id":1,
"number":"9005551234"
}
]
}
]
}
data/phone-numbers.json
{
"data":[
{
"id":7,
"contact_id":1,
"number":"6045551212"
},
{
"id":88,
"contact_id":1,
"number":"8009996541"
},
]
}
app.js:
Ext.Loader.setConfig({
enabled:true
});
Ext.application({
requires:[
'Assoc.model.Contact'
],
name:'Assoc',
appFolder:'Assoc',
launch:function(){
/* load child models that are in the response (uses associationKey): */
Assoc.model.Contact.load(1, {
success: function(record){
console.log(record.phoneNumbers());
}
});
/* load child models at will (uses foreignKey). this overwrites child model that are in the first load response */
Assoc.model.Contact.load(1, {
success: function(record){
record.phoneNumbers().load({
callback:function(){
console.log(arguments);
}
});
}
});
}
});
[1] A store will use its model's proxy. You can always override the store's proxy if need be. You won't be able to use Model.load() if the model has no proxy.

Your assumption is wrong. You expect that the WebSite store loads itself but that is not how it works. What you can do is the following (this is untested but is how I do it in all my projects):
In your clients grid add a listener for the itemclick event to call the following method (showWebSites). It will receive the selected client record containing the selected APP.model.Client instance. Then, and given that each client has a set of WebSites, the method will load the APP.store.Websites store and the client´s websites will be displayed in your view.
showWebSites: function (sender, selectedClient) {
Ext.StoreManager.lookup('APP.store.Websites')
.loadData(selectedClient.data.WebSites);
}
This is the way. I hope you find it useful.

Related

ExtJS — How to load store data manually after ajax call?

I rewrite my working Fiddle from ajax proxy type to memory. I'm trying to load memory store data manually:
// app/model/Employees.js file
Ext.define('Fiddle.model.Employees', {
extend: 'Ext.data.Model',
entityName: 'Employees',
fields: [
{
name: 'profile_pic'
},
{
type: 'int',
name: 'age'
},
{
type: 'string',
name: 'last',
mapping: 'name.last'
},
{
type: 'string',
name: 'first',
mapping: 'name.first'
},
{
type: 'string',
name: 'email'
}
],
proxy: {
type: 'memory',
reader: {
type: 'json',
rootProperty: 'items',
totalProperty: 'total',
successProperty: ''
}
}
});
// app/store/Employees.js file
Ext.define('Fiddle.store.Employees', {
extend: 'Ext.data.Store',
pageSize: 30, // items per page
alias: 'store.employees',
model: 'Fiddle.model.Employees',
});
//app.js fule - launch() function
var store = Ext.create('Fiddle.store.Employees');
console.log(store);
Ext.Ajax.request({
url: 'mates.json',
success: function(resp) {
var result = resp.responseText;
console.log(result);
// store.loadRawData(result);
store.loadData(result);
console.log(store);
console.log(store.getAt(0));
},
});
As result I have 3386 records in store, every symbol in my json file. And what I see in console as first record:
What I'm doing wrong?
And where I need to put proxy lines - in model or in store?
responseText is a string, which contains the serialized JSON data. You have to deserialize it into an object before you can use loadRawData to load the object through the model converters into the store:
var result = Ext.decode(resp.responseText);
store.loadRawData(result);
loadData and loadRawData differ in that loadData does not call the converters on the model. loadRawData is equivalent to what the ajax proxy does, loadData is not.
Did it in this way:
//in Grid panel js file
listeners: {
afterrender: function(grid, evt) {
var myStore = grid.getStore();
Ext.Ajax.request({
url: 'mates.json',
success: function(resp) {
var result = Ext.decode(resp.responseText);
myStore.getProxy().data = result;
myStore.load();
},
});
}
}
In store autoLoad: true must be disabled. This way of loading instead of store.loadRawData(result); shows the correct number of records in the pagingtoolbar.

Trying to build a Ext.data.Store with proxy, the request is fired but no data is pushed

I'm having the problem of my life.
Everytime I want to build a simple Ext.data.Store with a proxy (ajax), the request is fired I can see in my server the request at same time I put store.load(), but when I put some callback/check to my store like store.data.items or store.getProxy().reader.rawData, I got nothing.
Here is the code. It's simple, like the ExtJs doc's example:
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'Rule',
type: 'string'
},
]
});
var myStore = Ext.create('Ext.data.Store', {
model: 'User',
proxy: {
type: 'ajax',
url: '/product/getrule/'+product_id,
reader: {
type: 'json',
root: 'result["rules"]'
}
},
autoLoad: true
});
The json is like this:
"result":{
"name": "producttemplatte1",
"rules":[
{
"id": 1,
"rule":"rule1"
}
],
"active": true
}
I've tried everything. Ext.Ajax.requests too. I add the data from Ajax responses to the store and all, but the combobox store won't load (I guess it is because the asynchronous "A" from Ajax doesn't want to :/)

Store data is not loading ,when using proxy, but it is working fine with static

Store data is not loading ,when using proxy, but it is working fine with static.
means when I put hard codded data in my store , then it working fine.
my code is like blow...
model
Ext.define('new_app.model.BlogModel', {
extend : 'Ext.data.Model',
config : {
fields: [{
name: "firstName",
type: "string"
},{
name:"lastName",
type:"string"
}]
}
});
Store
Ext.define('new_app.store.blogs',{
extend:'Ext.data.Store',
config:{
model: "new_app.model.BlogModel",
proxy: {
type: 'ajax',
url: "data/testStore.js",
reader: {
type: 'json',
rootProperty: 'data'
}
},
autoLoad: true
}
});
And my view
Ext.define('new_app.view.Blog',{
extend:'Ext.navigation.View',
xtype:'blog',
requires:[
"Ext.dataview.List"
],
config: {
title:'Blog',
iconCls:'star',
items:[{
xtype:'list',
itemTpl: '<div class="contact">{firstName} <strong>{lastName}</strong></div>',
title:'Recent Posts',
store:'blogs'
}]
},
initialize: function(){
this.callParent();
// var storeData = Ext.widget('myblogs');
// console.log(storeData);
// this.setData(storeData);
}
});
Please help me.
It all looks good except that proxy/reader should be preferably configured on model, not on store. Now, how to debugg the thing:
Verify that there a request sent to the server (store is autoLoad so it should)
Verify that a valid json comes back
See if rootProperty matches that what comes in json
BTW, this looks like Sencha Touch, right?

Drupal nested json not working in Sencha touch

My json format
Ext.data.JsonP.callback3({"nodes":[
{"node":{"title":"Dane Sample Name - Owner/Stylist/Daymaker","field_headshot":"","body":"Born and raised in Carencro, La., Dane knew from a young age that he wanted to become a successful hairdresser. \n","nothing":""}},
{"node":{"title":"Rahul - Owner/Stylist/Daymaker","field_headshot":"","body":"Since 1995 Jeanne has enjoyed helping people to feel and look beautiful.\n","nothing":""}}]})
Models
Ext.define('SampleApp.model.Drupal', {
extend: 'Ext.data.Model',
uses: [
'SampleApp.model.Drupal2'
],
config: {
fields : [
'node'
],
},
hasMany: {
model: 'Drupal2',
name : 'node',
associationKey: 'node' ,
}
});
Ext.define('SampleApp.model.Drupal2', {
extend: 'Ext.data.Model',
config: {
fields: [
'title','body'
]}
});
Store
Ext.define('SampleApp.store.DrupalStore', {
extend: 'Ext.data.Store',
requires: [
'SampleApp.model.Drupal2'],
config: {
autoLoad : true,
model: 'SampleApp.model.Drupal2',
proxy: {
type: 'jsonp',
url: 'data/data.json',
reader: {
type: 'json',
rootProperty: 'nodes.node'
}
}
}
});
The above is the nested json from drupal view and I am trying to use those 2 models and store to load list in my view.I am trying to add list of titles from node but List is not loading in the view.If I give root property as nodes then it is loading all the data but not mapping to node.Please help me on where I am going wrong.
Changed my Model, it is not using associations.Here is the Model that worked for me
Ext.define('SampleApp.model.Drupal', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'title',
mapping: 'node.title', // mapping worked
},
{
name: 'field_headshot',
mapping : 'node.field_headshot',
},
{
name: 'body',
mapping : 'node.body',
}
],
}
});

Sencha touch list tpl with nested data

I'm new to sencha. I'm create MVC structure by use sencha architect, touch 2.2.x version.
I want to show nested data to a list control but I'm not sure how to define the tmp.
Here is sample of data return from server
{
"data":
[
{"AcctId": 1, "AcctNum": "A", "Alias": "aa"},
{"AcctId": 2, "AcctNum": "B", "Alias": "bb"},
{"AcctId": 3, "AcctNum": "C", "Alias": "cc"}
]
}
this is model, I define nested model
Ext.define('MyApp.model.Data', {
extend: 'Ext.data.Model',
uses: [
'MyApp.model.LoginAlias'
],
config: {
hasMany: {
model: 'MyApp.model.LoginAlias',
name: 'LoginAlias'
}
}
});
Ext.define('MyApp.model.LoginAlias', {
extend: 'Ext.data.Model',
config: {
fields: [
{
name: 'AcctId'
},
{
name: 'AcctNum'
},
{
name: 'Alias'
}
]
}
});
This is Stores to get data, It will be cross server data so I use JsonP
Ext.define('MyApp.store.MyJsonPStore', {
extend: 'Ext.data.Store',
requires: [
'MyApp.model.Data'
],
config: {
autoLoad: true,
model: 'MyApp.model.Data',
storeId: 'MyJsonPStore',
proxy: {
type: 'jsonp',
url: 'http://localhost:8000/test/get_alias/',
reader: {
type: 'json'
}
}
}
});
Finally the List
Ext.define('MyApp.view.MyList', {
extend: 'Ext.dataview.List',
config: {
store: 'MyJsonPStore',
itemTpl: [
'<div>List Item {AcctId}</div>'
]
}
});
I can see that the Store can get data from server in Sencha Architect by click on the "eye" icon next to the Store.
I try the List tpl with data.AcctId or change List store to MyJsonPStore.data but all not work.
Please help, thanks very much.
p/s: I try with non-nested model, and the List work ok. And this is the main js file, In case it needed
Ext.Loader.setConfig({
});
Ext.application({
models: [
'Data',
'LoginAlias'
],
stores: [
'MyJsonPStore',
'MyStore'
],
name: 'MyApp',
launch: function() {
Ext.create('MyApp.view.MyList', {fullscreen: true});
}
});
1. Data structure
Not sure it's useful to define MyApp.model.Data as it's only the root of your list of data. So you could give away the hasMany logic.
2. Data representation
Ext.dataview.List is designed to show simple lists only. For nested lists, consider extending Ext.dataview.NestedList. (but if 1. is true, you won't need it).
3. Data access
To get direct access to the data you need to display, simply add rootProperty: 'data' to your proxy's reader config object:
proxy: {
type: "jsonp",
url: 'http://server.ext/path/to/MyApp/app/data/sample.ashx',
reader: {
type: "json",
rootProperty: 'data'
}
}

Resources