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

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.

Related

ExtJS 6 inherited hasMany-Relation nested loading

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.

Filter by multilevel Deep Property

I have a collection somewhat like mentioned below:-
[
{
rootGroup: "group1",
secondGroup: false,
items: [
{name:"Ram"},
{name:"Mohan"},
{name:"Shyam"},
]
},
{
rootGroup: "group2",
secondGroup: true,
secondLevelGroups:[
{
group: "gp1"
items: [
{name:"Ganesh"},
{name:"Sita"},
{name:"Gita"},
]
},
{
group: "gp2"
items: [
{name:"Soham"},
{name:"Vikas"},
{name:"Ashish"},
]
}
]
}
]
Now I want to filter on name. So for example if the filter value is "am" then the output should be like as below.
[
{
rootGroup: "group1",
secondGroup: false,
items: [
{name:"Ram"},`
{name:"Shyam"},
]
},
{
rootGroup: "group2",
secondGroup: true,
secondLevelGroups:[
{
group: "gp2"
items: [
{name:"Soham"},
]
}
]
}
]
I want to do it using angularjs filter
Have you tried the extension angular filter: https://github.com/a8m/angular-filter

Binding of a Collection nested inside a Model

I have this model structure in my mind:
var app = app || {};
// Caratteristica
app.Attribute = Backbone.Model.extend({
defaults: {
name: '',
selected: false
}
});
app.Attributes = Backbone.Collection.extend({
model: app.Attribute
});
// Tipo Caratteristica
app.AttributeCategory = Backbone.Model.extend({
defaults: {
name: '',
attributes: new app.Attributes()
}
});
app.AttributeCategories = Backbone.Collection.extend({
model: app.AttributeCategory,
url: '/ajax/attributes.cfm'
});
My API in '/ajax/attributes.cfm' will give me a response like that:
[
{
"id": "1",
"name": "Type1",
"attributes": [
{
"id": "1",
"name": "Attribute1"
},
{
"id": "2",
"name": "Attribute2"
},
{
"id": "3",
"name": "Attribute3"
}
]
},
{
"id": "2",
"name": "Type2",
"attributes": [
{
"id": "1234",
"name": "Attribute1234"
},
{
"id": "2567",
"name": "Attribute2567"
}
]
}
]
My question is: will this json data be parsed correctly into my nested data structure?
I mean I want to end up having two app.AttributeCategory items in my app.AttributeCategories collection. Each of these two items must then have its attributes property filled with the corresponding app.Attributes collection.
If the answer was NO, how would I override the parse() function for achieving that result?
I did it like this:
// Tipo Caratteristica
app.AttributeCategory = Backbone.Model.extend({
defaults: {
name: ''
},
initialize: function(options) {
this.set('attributes', new app.Attributes(options.attributes));
Backbone.Model.prototype.apply(this, arguments);
}
});
But better use RationalModel for set up relations betweens models
You can create the collection inside an initialize method in your AttributeCategory model, like this:
app.AttributeCategory = Backbone.Model.extend({
...
initialize: function () {
this.set('attributes', new app.Attributes(this.get('attributes')));
}
});

Association Sample in extjs 4.2:

Can any one please point me to a working example of association (with hasMany and belongsTo) in ExtJS. Please don't point me to Sencha docs or any examples related to Sencha because I had tried almost everything but none of them works...
Running sample (turn on your browser console):
http://jsfiddle.net/4TSDu/52/
Ext.define('My.model.Author', {
extend:'Ext.data.Model',
fields:[
'name'
]
});
Ext.define('My.model.Comment', {
extend:'Ext.data.Model',
fields:[
'emailAddress',
'body'
]
});
Ext.define('My.model.BlogPost', {
extend:'Ext.data.Model',
fields:[
'title',
'body'
],
belongsTo:[
{
name:'author',
instanceName:'author',
model:'My.model.Author',
getterName:'getAuthor',
setterName:'setAuthor',
associationKey:'author'
}
],
hasMany:[
{
name:'comments',
model:'My.model.Comment',
associationKey:'comments'
}
],
proxy:{
type:'ajax',
url:'https://dl.dropboxusercontent.com/u/1015920/Ext/blog-posts.json',
reader:{
type:'json',
root:'data'
}
}
});
My.model.BlogPost.load(1, {
success:function(record, operation){
console.log(record.get('title')); // "some title"
console.log(record.getAuthor().get('name')); // "neil"
console.log(record.comments().getCount()); // 2
}
});
Read more here:
http://extjs-tutorials.blogspot.ca/2012/05/extjs-belongsto-association-rules.html
http://extjs-tutorials.blogspot.ca/2012/05/extjs-hasmany-relationships-rules.html
The sample data used:
{
"data": [
{
"id": 1,
"title": "some title",
"body": "some body",
"author": {"id":1, "name": "neil"},
"comments": [
{
"id":55,
"emailAddress": "user#example.com",
"body": "test comment"
},
{
"id":66,
"emailAddress": "user2#example.com",
"body": "another comment"
}
]
}
]
}

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)

Resources