ExtJS 6 inherited hasMany-Relation nested loading - extjs

I try to setup a hasMany relationship and want load my main entity with all the associated models in a single request.
But that seems not to work with "hasMany" relations that is inherited.
I have a BaseModel that defines all relations and fields and a "normal" model that defines the proxy to load from.
These are my (relevant) models:
Ext.define('MyApp.model.BaseUser', {
"extend": "Ext.data.Model",
"uses": [
"MyApp.model.UserEmail",
"MyApp.model.Account"
],
"fields": [
{
"name": "name"
},
{
"name": "accountId",
"reference": {
"type": "MyApp.model.Account",
"role": "account",
"getterName": "getAccount",
"setterName": "setAccount",
"unique": true
}
}
]
"hasMany": [
{
"name": "emails",
"model": "MyApp.model.UserEmail"
}
],
});
Ext.define('MyApp.model.User', {
extend: "MyApp.model.BaseUser",
proxy: {
type: 'rest',
url : '/api/user',
reader: {
type: 'json',
rootProperty: 'data',
}
}
});
Ext.define('MyApp.model.UserEmail', {
extend: 'Ext.data.Model',
"fields": [
{
"name": "id",
"type": "int"
},
{
"name": "email",
"type": "string"
},
],
proxy: {
type: 'rest',
url : '/api/user/email',
reader: {
type: 'json',
rootProperty: 'data',
}
}
});
// MyApp.model.Account looks like MyApp.model.UserEmail
This is my server's response:
{
data: [
{
name: 'User Foo'
accountId: 50
account: {
id: 50,
balance: 0
},
emails: [
{
id: 70,
email: 'hello#world.de'
}
]
}
]
}
The "account" relation is working on the "normal" User Model and I can access it via the auto-generated method user.getAccount() as I expected.
Now I tried to access the users emails with the auto-generated methods:
// user is of 'MyApp.model.User'
user.emails(); // store
user.emails().first(); // null
user.emails().count(); // 0
It seems that the "emails"-relation models were not loaded into my user model. Am I accessing them the right way?
I can access them via user.data.emails. But this is an array of plain objects, not of UserEmail-Objects.
Can anyone give me some advice? Is nested loading supported with keyless associations?
Kind regards,
czed
Edit:
Clearified what I ment.

It should work. Here's a working fiddle. Check console for nested loaded data.

Related

How do i modify a raw data object returned by an ExtJS AJAX proxy into a JSON object to be consumed by a Tree Store

In an effort to create a treepanel, i configure it with a treestore whose AJAX proxy url receives json data i have no control of. But using Ext.data.reader.Json's transform property invokable before readRecords executes, gives an option to modify the passed raw (deserialized) data object from the AJAX proxy into a modified or a completely new data object. The transform config, gives the code snippet below:
Ext.create('Ext.data.Store', {
model: 'User',
proxy: {
type: 'ajax',
url : 'users.json',
reader: {
type: 'json',
transform: {
fn: function(data) {
// do some manipulation of the raw data object
return data;
},
scope: this
}
}
},
});
I would please like an example on how to go about modifying the return JSON object
[
{
"id": 3,
"attributes":
{},
"name": "user_one",
"login": "",
"email": "user_one#ats",
"phone": "0751223344",
"readonly": false,
"administrator": false,
"password": null
},
{
"id": 4,
"attributes":
{},
"name": "user_two",
"login": "",
"email": "user_two#ats",
"phone": "0751556677",
"readonly": false,
"administrator": false,
"password": null
}
]
into a JSON object fit for a treestore.
The hierarchical tree is to be rendered to show which user is under which admin using a condition administrator==true from the returned JSON, then a second AJAX request that returns that admin's users shown here.
[
{
"user_id": 3,
"admin_id": 1,
},
{
"user_id": 4,
"admin_id": 2,
}
]
Is the data nested at all? Otherwise why use a treepanel instead of a grid? To your question though, it'll depend on how you configure your treepanel but it would probably be something like this:
transform: {
fn: function(data) {
var treeRecords = Ext.Array.map(data, function(i){
return {
text: i.name,
leaf: true
//any other properties you want
}
});
var treeData = {
root: {
expanded: true,
children: treeRecords
}
};
return treeData;
},
scope: this
}

angular-schema-form default, hidden values

I want to build a (section of a) form which produces the following output:
{
...
offers: {
context: "http://schema.org",
minPrice: 3
}
...
}
The catch is, context should always be present - the only field the user gets to manipulate is minPrice. Immediately, a hidden field with a value comes to mind. So here's the schema definition:
$scope.schema = {
...
offers: {
type: 'object',
properties: {
minPrice: {
type: 'number'
}
}
}
...
};
And here the form definition:
$scope.form = [
...
{
key: 'offers',
type: 'fieldset',
items: [
{
key: 'offers.minPrice',
type: 'number'
},
{
key: 'offers.context',
type: 'hidden',
default: 'http://schema.org'
}
]
}
...
];
However, observing the generated model it's obvious the entry context is not present. I have successfully used a combination of type: 'hidden' and default with a tabarray, but I just can't get it right with an object. I am using version 0.8.13 of angular-schema-forms - the latest at the time of this writing.
I'd appreciate any insights, thanks.
You must include context and it's default value within the schema in that version.
I expect that your issue relates to a bug which should have been fixed in the alphas for v1.0.0
It should work with:
Schema
{
"type": "object",
"properties": {
"offers": {
"type": "object",
"properties": {
"minPrice": {
"type": "number"
},
"context": {
"type": "string",
"default": "http://schema.org"
}
}
}
}
}
Form
[
{
"type": "fieldset",
"items": [
{
"key": "offers.minPrice",
"type":"number"
},
{
"key": "offers.context",
"type": "hidden",
"notitle": true
}
]
}
]

Association is not working in extjs4 when I am uploading my application to server?

I am working in extjs4 MVC. I am getting stuck at a point where I have been working on association.Association is working properly when I am using in my system local side.But when I am uploading it to server side then the associated data is not displaying.I am trying a lot but not getting answer how this conflict occurs.
My application is working properly at client side.It displays associated data also.But when when I uploading data to server side then it does not display associated data.
Here is my application's some part which is working at local side:--
But when I am uploading my side to server side then the options means associated data is not displayed
Here Is my some code:--
1) Model class :--
Ext.define('B.model.kp.PollModel',{
extend: 'Ext.data.Model',
idproperty:'',//fields property first position pk.
fields: ['pollId','pollQuestion','isActive','pollTypeId','createDate','userId','publishDate','isPublished','approvalUserId','percentagevotes','optionId'],
hasMany:{
model:'B.model.kp.PolloptionModel',
foreignKey:'pollId',
name:'options',
},
proxy:
{
type:'ajax',
api:
{
read:'index.php/KnowledgePortal/Poll/GetPublicPoll',
create:'index.php/KnowledgePortal/Pollvote/setPollVote',
},//End of api
reader:
{
type:'json',
root: 'polls',
//successProperty: ,
},//End of reader
writer:
{
type:'json',
root: 'records',
//successProperty: ,
},
}//End of proxy
});
2) Store class :--
Ext.define('B.store.kp.PollStore',{
extend: 'Ext.data.Store',
model: 'B.model.kp.PollModel',
autoLoad: true,
});//End of store
3) View class:--
Ext.define('B.view.kp.poll.PollView',{
extend:'Ext.view.View',
id:'pollViewId',
alias:'widget.PollView',
store:'kp.PollStore',
config:
{
tpl:'<tpl for=".">'+
'<div id="main">'+
'</br>'+
'<b>Question :-</b> {pollQuestion}</br>'+
'<tpl for="options">'+
'<p>{#}.<input type="radio" name="{parent.pollId}" value="{optionId}">&nbsp{option}</p>'+
'</tpl></p>'+
'</div>'+
'</tpl>',
itemSelector:'div.main',
},
});// End of login class
4) here is my main view class
Ext.define('B.view.kp.poll.Poll',{
extend:'Ext.form.Panel',
requires:[
'B.view.kp.poll.PollView'
],
id:'pollId',
alias:'widget.Poll',
title:'Poll',
//height:180,
items:[
{
xtype:'PollView',
},
],//end of items square
buttons:[
{
disabled:true,
name:'vote',
formBind:true,
text:'vote',
action:'voteAction'
},
{
text:'result',
action:'resultAction',
}
]
});
5) And here is the json file --
{
'polls': [
{
"pollId": 1,
"pollQuestion": 'Who will win the match',
"options": [
{
"optionId":1,
"option":'India',
"pollId":1
},
{
"optionId": 2,
"option": 'Pakistan',
"pollId":1
},
{
"optionId": 3,
"option": 'Srilanka',
"pollId":1
},
{
"optionId": 4,
"option": 'Australia',
"pollId":1
},
],
}
]
}
6) PollOption model class :--
Ext.define('B.model.kp.PolloptionModel',{
extend: 'Ext.data.Model',
//idproperty:'',//fields property first position pk.
fields: ['optionId','option','pollId','percentagevotes'],
associations:[
{type:'HasMany', model:'Pollvotemodel', foreignKey:'optionId'},
{type:'BelongsTo', model:'PollModel', foreignKey:'pollId'},
]
});
Please someone give me some suggestion to solve this problem...
are you sure your server-side data feed is exactly the same as your local data feed.
Are the related questions entered into the live database?

Not giving Parent data from Child in association in extjs

Hope you are doing good.
I am new in extjs4 and working on sample example of association.
I have 2 different class User and Diploma
In relation, I have defined.
User hasMany Diplomas, and Diplomas belongsTo User
My models are as belows
User.js
Ext.define('MyApp.model.User', {
extend : 'Ext.data.Model',
idProperty : 'userId',
fields : [{
name : 'userId',
type : 'integer'
}, {
name : 'userName',
type : 'string',
}],
hasMany : {
model : 'MyApp.model.Diploma',
name : 'diplomas',
},
});
Diploma.js
Ext.define('MyApp.model.Diploma', {
extend : 'Ext.data.Model',
idProperty : 'diplomaId',
fields : [{
name : 'diplomaId',
type : 'integer'
}, {
name : 'diplomaName',
type : 'string',
}, {
name : 'userId',
type : 'integer'
}],
associations : [{
model : 'MyApp.model.User',
name : 'user',
type : 'belongsTo'
}]
});
=====================
My Stores are as below.========================
Diploma.js
Ext.define('MyApp.store.Diploma', {
extend : 'Ext.data.Store',
model : 'MyApp.model.Diploma',
autoLoad : true,
listeners : {
'load' : {
fn : function(store, records, success, operation) {
console.log('Diplomas are loaded');
}
}
}
});
User.js
Ext.define('MyApp.store.User', {
extend : 'Ext.data.Store',
model : 'MyApp.model.User',
requires:['Ext.data.proxy.LocalStorage'],
autoLoad : true,
listeners : {
'load' : {
fn : function(store, records, success, operation) {
console.log('User is loaded');
}
}
},
data : [{
userId : 1,
userName : 'Rishabh Shah',
diplomas:{
userId : 1,
diplomaId:1,
diplomaName:'IT'
}
}, {
userId : 2,
userName : 'Rakesh Shah',
diplomas:{
userId : 2,
diplomaId:2,
diplomaName:'CE'
}
}, {
userId : 3,
userName : 'Rashmin Shah'
}],
proxy:{
type:'memory',
reader:{
root:'data'
}
}
});
I can get diploma from user like that and can get result
Ext.getStore("User").getAt(0).diplomasStore.getAt(0)
but, when I try to do like
Ext.getStrore("Diploma") or Ext.getStrore("Diploma").getAt(0)
I don't get anything. items contains nothing...
How can I get user from diploma.
and One more thing....if I don't write proxy in my Diploma model..
it gives me an error like this..
Ext.data.proxy.Server.buildUrl(): You are using a ServerProxy but have not supplied it with a url.
Please guide me.
Thanks.
Thanks for your reply..#john..I can get diplomas from User..
I wanted to get user from diplomas...I tried it myself..and found solution...
I will have following json.
[
{
"depId": 1,
"depName": "CE",
"employees": [
{
"empId": 1,
"firstName": "Rishabh",
"lastName": "Shah"
}, {
"empId": 2,
"firstName": "Smit",
"lastName": "Patel"
}
]
}, {
"depId": 2,
"depName": "IT",
"employees": [
{
"empId": 1,
"firstName": "Parag",
"lastName": "Raval"
}, {
"empId": 2,
"firstName": "Rakesh",
"lastName": "Prajapati"
}
]
}, {
"depId": 3,
"depName": "EE",
"employees": [
{
"empId": 1,
"firstName": "Parag EE",
"lastName": "Raval EE"
}, {
"empId": 2,
"firstName": "Rakesh EE",
"lastName": "Prajapati EE"
}
]
}, {
"depId": 4,
"depName": "EC",
"employees": [
{
"empId": 1,
"firstName": "Parag EC",
"lastName": "Raval EC"
}, {
"empId": 2,
"firstName": "Rakesh EC",
"lastName": "Prajapati EC"
}
]
}, {
"depId": 5,
"depName": "Chemial E",
"employees": [
{
"empId": 1,
"firstName": "Parag",
"lastName": "Raval"
}, {
"empId": 2,
"firstName": "Rakesh",
"lastName": "Prajapati"
}
]
}, {
"depId": 6,
"depName": "ME",
"employees": [
{
"empId": 1,
"firstName": "Parag",
"lastName": "Raval"
}, {
"empId": 2,
"firstName": "Rakesh",
"lastName": "Prajapati"
}
]
}, {
"depId": 7,
"depName": "Civil Engineer",
"employees": [
{
"empId": 1,
"firstName": "Parag",
"lastName": "Raval"
}, {
"empId": 2,
"firstName": "Rakesh",
"lastName": "Prajapati"
}
]
}
]
and I will use model.getAssociatedData().user as per my requirement
where model is my record of child class and user is my parent class..
and I was using proxy in my Diploma Model which was not requierd....so, was getting
Ext.data.proxy.Server.buildUrl(): You are using a ServerProxy but have not supplied it with a url.
above mentioned error.
Thanks All ! :)
What exactly isn't working? Have you been able to use the magic methods e.g., User.diplomas()? As #VDP stated, the store created for the Association is a normal Ext.data.Store scoped to the set of data for the parent model (in this case, User). That is to say, if you have a User model with the id of 1, calling the method User.diplomas() will return a Ext.data.Store filtered to contain only Diploma's with a user_id of 1.
This is very important to understand! If you do not specify the foreignKey property in a hasMany association, it will default to the lowercased name of the owner model plus "_id", You should amend your User model's hasMany association as so:
Ext.define('MyApp.model.User', {
/** Model Definition */
hasMany : {
model : 'MyApp.model.Diploma',
name : 'diplomas',
foreignKey : userId /** This is what you're missing */
}
});
Perhaps you will find this blog post useful? http://extjs-tutorials.blogspot.com/2012/05/extjs-hasmany-relationships-rules.html
Some important tips from the blog post (in case the link dies at some point)
Always put your Proxies in your Models, not your Stores, unless you
have a very good reason not to *
Always require your child models if using them in hasMany
relationships. **
Always use foreignKey if you want to load the children at will
Always use associationKey if you return the children in the same
response as the parent
You can use both foreignKey and associationKey if you like
Always name your hasMany relationships
Always use fully qualified model names in your hasMany relationship
Consider giving the reader root a meaningful name (other than "data")
The child model does not need a belongsTo relationship for the
hasMany to work
*The store will inherit its model's proxy, and you can always override it
**To make it easy, and avoid potential circular references, you can require them in app.js
Credit: Neil McGuigan (http://www.blogger.com/profile/14122981831780837323)

Can you define a hasMany relationship with a HashMap in an extJs model?

I have some json data with the following format:
{
"id":1,
"personMap":{
"president":{"firstname":"Sookie","lastname":"Stackhouse"},
"vicepresident":{"firstname":"Eric","lastname":"Northman"},
"treasurer":{"firstname":"Alcide","lastname":"Herveaux"}
}
}
How do I define my model so that the values in the map are loaded with the correct object type? Is that possible?
The following will load the data but the values are not typed as 'Person' objects:
Ext.define('Committee', {
extend: 'Ext.data.Model',
fields: [ 'id', 'personMap' ]
});
The following would expect personMap to be an array not a map:
Ext.define('Committee', {
extend: 'Ext.data.Model',
fields: [ 'id' ],
hasMany: [{
model: 'Person',
name: 'personMap'
}]
});
Ext.define('Person', {
extend: 'Ext.data.Model',
fields: [ 'firstname', 'lastname' ]
});
The hasMany config only applies to arrays. Changing the data structure to,
{
"id": 1,
"personMap": [
{
"firstname": "Sookie",
"lastname": "Stackhouse",
"title": "president"
},
{
"firstname": "Eric",
"lastname": "Northman",
"title": "vicepresident"
},
{
"firstname": "Alcide",
"lastname": "Herveaux",
"title": "treasurer"
}
]
}
will do the trick, but if that's not an option then the hasMany config cannot be used.

Resources