I have a situation where I have a model meant to store several lists of chemicals. The chemical model is the same for each of the hasMany relationships.
I need something like this:
Ext.define('HandSurvey.model.ChemicalRisks', {
extend: 'Ext.data.Model',
requires: ['Ext.data.identifier.Uuid'],
config: {
idProperty: 'id',
identifier: 'uuid',
fields: [
{ name: 'id', type: 'auto' }
],
associations: [
{
type: 'hasMany',
model : 'HandSurvey.model.SpecificChemical',
name : 'fiberglassResins',
store : {
type: 'sql'
}
},
{
type: 'hasMany',
model : 'HandSurvey.model.SpecificChemical',
name : 'paintsStains',
store : {
type: 'sql'
}
},
],
proxy: {
type: 'sql'
}
}
});
But this would cause each list to bind to every SpecificChemical that belongs to the ChemicalRisks model, not just the ones meant to belong to that hasMany. It seems as though I would need to join on multiple fields
Is it possible to do this? Or do I have to make a bunch of the exact same models/stores with different names?
sure you can!
use associationKey and the autogenerated stores of the associations
associations: [
{
type: 'hasMany',
model : 'HandSurvey.model.SpecificChemical',
name : 'fiberglassResins',
associationKey : 'fiberglassResins'
},
{
type: 'hasMany',
model : 'HandSurvey.model.SpecificChemical',
name : 'paintsStains',
associationKey : 'paintsStains'
},
]
Given a response like this: {
"response" : {
"fiberglassResins": [
{
"id" : 1
"name" : "Polyester"
},
{
"id" : 2
"name" : "E-Glass"
}
],
"paintsStains": [
{
"id" : 1
"name" : "item1"
},
{
"id" : 2
"name" : "item2"
}
]
}
}
Then you bind your main model to a store lets say ItemsStore.
IMPORTANT each record of ItemsStore will get autogenerated by Sencha: fiberglassResinsStore and paintsStainsStore.
Yo can console.log() each record to see the actual stores.
Related
demoAlerts({
itemstatus: [
{
item: "1",
name: "apple",
type: "fruit"
},
{
item: "2",
name: "pine",
type: "fruit"
}
],
deliverystatus: [
{
name: "james",
status: "yes"
},
{
name: "thomas",
status: "no"
},
]
});
I have two array (itemstatus and deliverystatus), I need to create the model for this store. what I tried is
ParentModel:
Ext.define('test.model.ParentModel', {
extend: 'Ext.data.Model',
requires:['test.model.ItemModel','test.model.DeliveryModel'],
autoLoad: true,
config : {
fields : [ 'itemstatus', {
name : 'demostatuslist',
model : 'demoAlerts.model.ItemModel',
mapping : 'itemstatus'
},
'portalstatus', {
name : 'deliverystatus',
model : 'test.model.DeliveryModel',
mapping : ' deliverystatus'
}]
}
});
ItemModel
Ext.define('demoAlerts.model.ItemModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'item', type: 'string' },
{ name: 'name', type: 'string' },
{ name: 'type', type: 'string' }
]
}
});
DeliveryModel
Ext.define('demoAlerts.model.DeliveryModel', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'name', type: 'string' },
{ name: 'status', type: 'string' },
]
}
});
Whether i properly configured the model. I am receiving the store as empty
Use Associations :) http://docs.sencha.com/touch/2.3.1/#!/api/Ext.data.association.Association
In this case I would have a Model with 2 hasMany associations like this:
Ext.define('demoAlerts.model.ContainerModel', {
extend : 'Ext.data.Model',
requires : [
'demoAlerts.model.DeliveryModel',
'demoAlerts.model.ItemModel'
],
config : {
associations: [
{
type : 'hasMany',
model : 'demoAlerts.model.DeliveryModel',
associationKey : 'deliveryStatus',
name : 'deliveryStatus',
autoLoad : true // this is very important
},
{
type : 'hasMany',
model : 'demoAlerts.model.ItemModel',
associationKey : 'itemStatus',
name : 'itemStatus',
autoLoad : true // this is very important
}
]
}
});
Then use a store SomeStore binded to ContainerModel.
IMPORTANT Each record in SomeStore will have deliveryStatusStore and itemStatusStore AUTOGENERATED.
Read about associations.
Neither http://docs.sencha.com/touch/2.3.1/#!/api/Ext.data.Field
nor http://docs.sencha.com/extjs/5.0/apidocs/#!/api/Ext.data.field.Field
knows a valid config option "model" for a field.
As far as I know, there is no such thing as a "Parent Model" available in ExtJS or Sencha Touch.
As far as I know, there is no possibility to have two stores in one.
You can load two (or more) stores using only one call to the server like in my following example:
firststore.on('load',function() {
secondstore.loadRawData(firststore.getProxy().getReader().rawData);
});
firststore.load()
Where you would give firststore the server url and the root of the data that goes into the first store, and secondstore will have the root of the data that goes into the second store.
Please be aware that the second store won't be filled if zero records go into the first store, and choose your stores appropriately.
If any of your stores can be the only empty store, perhaps you will have to get the rawdata via Ext.data.Request and load it into all stores afterwards.
I have two Stores 'Polls' and 'Choices' with respective models as 'Poll' and 'Choice'
models
Poll
Ext.define('PollsTest.model.Poll', {
extend: 'Ext.data.Model',
xtype : 'poll',
config: {
fields: [
{ name: 'title'},
{ name: 'uri' },
],
hasMany :
[
{
model : 'PollsTest.model.Choices',
name : 'Choices',
primaryKey : 'title',
foreignKey : 'title',
foreignStore : 'Choices'
}
]
}
});
Choice
Ext.define('PollsTest.model.Choice', {
extend: 'Ext.data.Model',
config: {
fields: [
{ name: 'choice', type: 'auto' },
{ name: 'votes', type: 'auto' },
{name : 'title', type: 'auto'},
{name : 'uri', type : 'auto'}
],
belongsTo : {
model : 'PollsTest.model.Choices',
name : 'Choices',
primaryKey : 'title',
foreignKey : 'title',
foreignStore : 'Choices',
getterName: 'getChoices',
setterName: 'setChoices'
}
}
});
Stores
Polls
Ext.define('PollsTest.store.Polls',{
extend : 'Ext.data.Store',
alias : 'store.pollStore',
//xtype:'pollStore',
requires :
[
'PollsTest.model.Poll',
'Ext.data.proxy.JsonP',
'Ext.data.reader.Json'
],
config :
{
autoLoad : true,
model : 'PollsTest.model.Poll',
storeId :'pollStore',
listeners :
{
load : function(store, records)
{
console.log('store loaded',records);
}
},
//storeId : 'pollstore',
proxy :
{
type : 'jsonp',
url : 'http://localhost/polls',
reader :
{
type : 'json',
rootProperty : 'polls'
}
}
},
});
Choices
Ext.define('PollsTest.store.Choices',{
extend : 'Ext.data.Store',
alias : 'store.choiceStore',
requires :
[
'PollsTest.model.Choice'
],
config :
{
autoLoad : false,
model : 'PollsTest.model.Choice',
storeId :'choiceStore',
listeners :
{
load : function(store, records)
{
console.log('choice store loaded',records);
}
},
proxy :
{
type : 'jsonp',
url : '',
reader :
{
type: 'json',
rootProperty : 'choices'
}
}
},
});
So from Polls store I can populate my List and upon clicking the list item the controller pushes the detail panel to the view. The Choices Store will populate based on the tap event occurred on the list. So the problem is I have to push the details panel to the view only after loading the Choices Store
How can I do that?? Suggestions are appreciated.
and My controller will look like this
Ext.define('PollsTest.controller.MainController', {
extend: 'Ext.app.Controller',
requires : ['PollsTest.controller.ChoiceController'],
config: {
refs: {
mainController : 'mainpanel',
controller_list : 'pollslist',
details_controller : 'pollsdetails'
},
control: {
controller_list :
{
itemtap : 'ShowPoll'
},
}
},
ShowPoll : function (list, index, target, record, e, eOpts)
{
var tochoice = record.data.uri;
var main_path = 'http://localhost';
var choices_url = main_path+tochoice;
var choice_store_object = Ext.getStore('choiceStore');
choice_store_object.getProxy().setUrl(choices_url);
choice_store_object.load();
console.log(choice_store_object.getCount());
/* var choices_store_object = Ext.create('PollsTest.store.Choices');
var checking = choices_store_object.on('load',function(){return true;});
if(checking==true) --> didn't work no detail panel pushing is happening but the order of loading the stores works fine here.
{
*/ console.log('before pushing');
this.getMainController().push({xtype : 'pollsdetails',data : record.data });
console.log('after Pushing');
// }
//this.getApplication().getController('ChoiceController').onDetailsShow(this,record,tochoice);
}
});
You can pass a callback function in your choice store load function. The callback function will be executed after the store has loaded.
choice_store_object.load(function(records, operation, success) {
// push the pollsdetails view here
}, this);
This is how I `i have implemented
var choices_store_object = Ext.create('PollsTest.store.Choices');
var checking =choice_store_object.load(function(records, operation, success)
{
console.log('before pushing');
this.getMainController().push({xtype : 'pollsdetails',data : record.data });
console.log('after Pushing');
}, this);
`
I successfully tried sencha touch app example showed here
They are using store proxy type as localstorage, its working good and then i changed the proxy type to sql as shown below
Ext.define('notesApp.store.Notes', {
extend : 'Ext.data.Store',
requires : 'Ext.data.proxy.Sql',
config : {
model : 'notesApp.model.Note',
proxy : {
type : 'sql',
database: "SqlProxyTest",
table: "Notes",
id : 'notes-app-store'
},
sorters : [{property : 'dateCreated', direction : 'DESC'}],
grouper : {
sortProperty : 'dateCreated',
direction : 'DESC',
groupFn : function(record) {
if(record && record.data.dateCreated) {
return record.data.dateCreated.toString();
}
return '';
}
}
}
});
There is no error.
I can insert data and i can see the record in list view, but chrome resource showing "The Node table is empty".
If i refresh the browser the record is gone from the list.
Am i missing anything or is it right way to use sql proxy in sencha touch ?
If you have change your model (add a field) you have to drop the table and recreate it.
And when you add a new row on your datastore be sure to put all fields.
Example if i have a model with firstName, lastName, email :
// This one is not added cause email is absent
Ext.getStore('Users').add([{
firstName: 'Toto',
lastName: 'test',
}]);
// This one is added
Ext.getStore('Users').add([{
firstName: 'toto',
lastName: 'test',
email : 'toto#test.te'
}]);
The mistake i did was, i created id for the record i am trying to insert as they showed in that demo example, when i changed below model from
Ext.define("NotesApp.model.Note", {
extend: "Ext.data.Model",
config: {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'dateCreated', type: 'date', dateFormat: 'c' },
{ name: 'title', type: 'string' },
{ name: 'narrative', type: 'string' }
]
}
});
to
Ext.define('notesApp.model.Note', {
extend : 'Ext.data.Model',
config : {
fields : [
{ name : 'dateCreated', type : 'string', dateFormat : 'D'},
{ name : 'title', type : 'string'},
{ name : 'narrative', type : 'string'}
],
validations : [
{type : 'presence', field : 'dateCreated'},
{type : 'presence', field : 'title', message : 'Please enter a title for the note!'}
]
}
});
Everything works fine.
I have a TreeStore, which works fine, but every node has some nested data, so I made a new model for it and used the hasMany association. But now the store loads nothing anymore. When I look into the records in the load event, they're empty, but the browser tells me the Ajax request delivered everything like before.
This is what the node data looks like, when it comes from the server:
{
"path": "KEY_518693",
"name": "KEY_518693",
"data": [
{
"branch": "KEY_518693",
"primnav": "ETC",
"X": 29261,
"Y": 96492
},
...
],
"children": [ ... ],
...
}
These are my model definitions:
TreeNode:
{
extend : 'Ext.data.Model',
requires: [
'DataRecord',
'Ext.data.association.HasMany'
],
fields : [
{ name: 'id' , type: 'string', mapping: 'path' },
{ name: 'text', type: 'string', mapping: 'name' },
...
],
hasMany : {
model: 'DataRecord',
name : 'data'
}
DataRecord:
{
extend: 'Ext.data.Model',
fields: [
{ name: 'branch' , type: 'string'},
{ name: 'primnav', type: 'string' },
{ name: 'X' , type: 'int' },
{ name: 'Y' , type: 'int' }
]
}
When I remove the association, the tree loads without problems. When I add data to the fields it gets parsed into the tree, but as "raw" object and not as model instance.
Please note that DataRecord has no field called treenode_id - so your hasMany association isn't complete. See docs for more info.
My approach had 2 problems.
The name of the association should not be 'data' or the records wont get loaded at all.
The primaryKey of the association has to be set right, in my case 'branch' was right
I have two models defined, ScoreCard and CaregoryWeight. A ScoreCard has many CategoryWeights.
When I create a grid and pass the association store to it (scoreCard.categoryWeights()), it displays nothing even though items are returned from the RESTful service.
What is wrong? please help.
Below is my code:
Ext.define(ModelNames.CategoryWeight, {
extend : 'Ext.data.Model',
idProperty : 'id',
fields : [ {
name : 'id',
type : 'int'
}, {
name : 'weight',
type : 'float'
}, {
name : 'category_id',
type : 'int'
}, {
name : 'scorecard_id',
type : 'int'
} ],
associations : [ {
type : 'belongsTo',
model : ModelNames.Category,
primaryKey : 'id',
forgientKey : 'category_id'
}, {
type : 'belongsTo',
model : ModelNames.ScoreCard,
primaryKey : 'id',
forgientKey : 'scorecard_id'
} ]});
Ext.define(ModelNames.ScoreCard, {
extend : 'Ext.data.Model',
idProperty : 'id',
fields : [ {
name : 'id',
type : 'int'
}, {
name : 'description',
type : 'string',
defaults : ''
}, {
name : 'isTemplate',
type : 'boolean',
defaults : true
}, {
name : 'isValid',
type : 'boolean',
defaults : false
} ],
associations : [ {
type : 'hasMany',
model : ModelNames.ScoreRecord,
name : 'scoreRecords',
storeConfig : {
autoLoad : true,
autoSync : true,
proxy : {
type : 'rest',
url : '/' + CONTEXT_PATH + '/RESTFul/ScoreRecord',
reader : {
type : 'json',
root : 'items'
},
writer : 'json'
}
}
}, {
type : 'hasMany',
model : ModelNames.CategoryWeight,
name : 'categoryWeights',
storeConfig : {
autoLoad : true,
autoSync : false,
proxy : {
type : 'rest',
url : '/' + CONTEXT_PATH + '/RESTFul/CategoryWeight',
reader : {
type : 'json',
root : 'items'
},
writer : 'json'
}
}
} ]});
Typo: foreignKey
Since answers are not allowed to be less than two words, I'll add that apart from spotting the typo, I have no idea if your code will work, why or why not.