Extjs binding a form to a model that has associations - extjs

I have the following JSON structure:
userAuth
----userAccount -- hasOne
----userAccountDetails -- hasMany
I want to show a form that shows data from userAuth and userAccount and then a grid with a row for each row in userAccountDetails
Here is the code for userAuth model:
Ext.define('xxxx.model.UserAuth', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id' },
{ name: 'email' },
{ name: 'userName' },
{ name: 'refIdStr' },
{ name: 'displayName' },
{ name: 'modifiedDate', type: 'date', }
],
requires: [
'xxxx.model.UserAccount',
'xxxx.model.UserAuthDetails',
],
hasMany: [
{
model: 'xxxx.model.UserAuthDetails',
name: 'authDetails',
foreignKey: 'userAuthId',
associationKey: 'userAuthDetails',
}
],
hasOne: [
{
model: 'xxxx.model.UserAccount',
name: 'userAcount',
associationKey: 'userAccount',
getterName: 'getUserAccount',
setterName: 'setUserAccount',
}
],
proxy: {
type: 'ajax',
startParam: 'skip',
limitParam: 'take',
url: settings.ApiUrl + '/model/UserAuth/?format=json',
baseParams: {
skip: '0',
take: '10',
},
reader: {
type: 'json',
root: 'results',
successProperty: 'success',
totalProperty: 'totalCount'
}
}
});
And userAccount model
Ext.define('xxxx.model.UserAccount', {
extend: 'Ext.data.Model',
fields: [
{ name: 'username' },
{ name: 'id' },
{ name: 'name' },
{ name: 'email' },
{ name: 'slug' },
{ name: 'facebookId' }
],
belongsTo: 'xxxx.model.UserAuth',
proxy: {
type: 'ajax',
startParam: 'skip',
limitParam: 'take',
url: settings.ApiUrl + '/model/UserAccount/?format=json',
baseParams: {
skip: '0',
take: '10',
},
reader: {
type: 'json',
root: 'results',
successProperty: 'success',
totalProperty: 'totalCount'
}
}
});
and userAuthDetails:
Ext.define('xxxx.model.UserAuthDetails', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id' },
{ name: 'userAuthId' },
{ name: 'provider' },
{ name: 'userId' },
{ name: 'userName' },
{ name: 'displayName' },
{ name: 'firstName' },
{ name: 'lastName' },
{ name: 'email' },
{ name: 'modifiedDate' },
{ name: 'provider' },
],
belongsTo: [
{
model: 'xxxx.model.UserAuth',
isntanceName: 'userAuth',
getterName: 'getUserAuthDetails',
setterName: 'setUserAuthDetails',
associationKey: 'userAuthDetails'
}
],
proxy: {
type: 'ajax',
startParam: 'skip',
limitParam: 'take',
url: settings.ApiUrl + '/model/UserAuthDetails/?format=json',
baseParams: {
skip: '0',
take: '10',
},
reader: {
type: 'json',
root: 'results',
successProperty: 'success',
totalProperty: 'totalCount'
}
}
});
Loading the store works and the associations work - when i call record.getUserAccount().get('email') it returns what I'd expect - so all that is working.
Now, my question is - how the hell do i get that data into the form described above?
I have tried doing things like:
{
xtype: 'textfield',
fieldLabel: 'username',
allowBlank: false,
maxLength: 100,
name: 'userAccount.userName'
}
thinking the association name might be a good hint for it - but that doesn't work...
Data from the top most model (userAuth) works ok - I just can't seem to pull in the hasOne
into the form.
I haven't even tried binding the userAuthDetails to a grid yet but suspect that will be equally as challenging
Has anyone managed to get this to work? I only went down the associations route because i thought it would make this sort of stuff cleaner / simpler!
[EDIT]
Giving up trying to do this with a form as I am happy for this data to be read only for now. I am now trying to show this data in an xtemplate within a row expander.
I've tried the following but it does not work!!!
plugins: [
{
ptype: 'rowexpander',
rowBodyTpl: [
'<p><b>Username:</b> {userName}</p>',
'<p><b>Email:</b> {userAccount.email}</p>',
'<tpl for="userAuthDetails">',
'<p>{provider}</p>',
'</tpl>'
]
}],
What sort of voodoo do I need to make this work? It is not obvious at all!!!
ATM I am thinking I won't be using ExtJs again - I've found myself in too many dark holes like this recently where things blatantly should just work the way you'd expect - just googling this shows everyone expects this to work. I've used ExtJs on and off for years but I think now is the time to finally admit there are better js application frameworks out there.

Unfortunately, there is no automatic, config-only way of how to do that. If you look at the loadRecord source you see that it just gets data from the passed record and calls setValues on the form.
You would need to override loadRecord method to dig the required values from the associated record(s).

Related

Using multiple model associations with bindings

I am using ExtJS 6.x with three models:
Ext.define('Admin.model.Patient', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.proxy.Rest',
'Ext.data.schema.Association'
],
fields: [
{ name: 'id', type: 'string' },
{ name: 'mrn', type: 'string' },
{ name: 'birth_date', type: 'date', format: 'Y-m-d' },
{ name: 'sex', type: 'string' },
{ name: 'first_name', type: 'string' },
{ name: 'last_name', type: 'string' },
],
style: {
'font-size': '22px',
'color':'red'
},
proxy: {
type: 'ajax',
url: remote.url.patient,
reader: {
type: 'json',
rootProperty: ''
}
}
});
Ext.define('Admin.model.LabResultGroup', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{ name: 'test_code', type: 'string' },
{ name: 'test_name', type: 'string' },
{
name: 'patient_id',
type: 'string',
reference: {
parent: 'Patient',
inverse: 'lab_results',
autoLoad: false
}
}
],
proxy: {
type: 'ajax',
url: remote.url.labsgroup,
reader: {
type: 'json',
rootProperty: ''
}
});
and
Ext.define('Admin.model.LabResult', {
extend: 'Ext.data.Model',
idProperty: 'id',
fields: [
{ name: 'test_code', type: 'string' },
{ name: 'test_name', type: 'string' },
{ name: 'test_code_system', type: 'string' },
{ name: 'result_value', type: 'string' },
{ name: 'result_value_num', type: 'string' },
{ name: 'collection_datetime', type: 'date', format: 'Y-m-d' },
{ name: 'result_datetime', type: 'date', format: 'Y-m-d' },
{
name: 'lab_id',
type: 'string',
reference: {
parent: 'LabResultGroup',
inverse: 'lab_group',
autoLoad: false
}
}
],
proxy: {
type: 'ajax',
url: remote.url.labs,
reader: {
type: 'json',
rootProperty: ''
}
}
});
I can access the association between LabResultGroup and Patient just fine (between two comboboxes using bindings), but when I try accessing the association between LabResult and LabResultGroup, it does not register.
I will post a Fiddle in due course to exhibit the behavior I am encountering. Is there anything that would prevent associations across models like this?
It actually worked! For some odd reason the parent name in the association on my LabResult model got mucked up. Corrected that, and my association bindings are firing as expected.
(Also, there was a minor problem with the API endpoint I was accessing. I had to add another condition for the property on which it was filtering. Details, shmetails)
Moral of the story: Names are important! Happy Friday peeps! Ha! Ha!

Is Sencha ExtJS association POST wrong?

So, I have a problem using Sencha ExtJs 4.1 Associations.
I have something like:
Models
Ext.define('Tpl.model.User', {
extend: 'Ext.data.Model',
requires: ['Tpl.model.PostTemplate'],
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' },
{ name: 'postTemplate', type: 'int' }
],
associations: [
{ type: 'belongsTo', name: 'postTemplate', model:'Tpl.model.PostTemplate', associationKey: 'postTemplate', primaryKey: 'id', foreignKey: 'postTemplate' }
]
});
and
Ext.define('Tpl.model.PostTemplate', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int' },
{ name: 'blah', type: 'string' }
],
associations: [
{ type: 'hasMany', model: 'Tpl.model.User' }
]
});
Stores
Ext.define('Tpl.store.Users', {
extend: 'Ext.data.Store',
model: 'Tpl.model.User',
autoLoad: true,
proxy: {
type: 'rest',
url: '../users',
reader: {
type: 'json',
root: ''
},
writer: {
type: 'json'
}
}
});
Ext.define('Tpl.store.PostTemplate', {
extend: 'Ext.data.Store',
model: 'Tpl.model.PostTemplate',
autoLoad: true,
proxy: {
type: 'rest',
//appendId: true,
url: '../postTemplates/',
reader: {
type: 'json',
root: ''
},
writer: {
type: 'json'
}
}
});
The problem is that I'm getting a POST like this:
{
"postTemplate": 1,
"id": 0,
"name": "foo"
}
But I need a POST like this:
{
"postTemplate": {
"id": 1,
"blah": "foo"
},
"id": 0,
"name": "bar"
}
Also, the assessor function like "setPostTemplate" doesn't exist and I think it should be created automatically.
Already tried to something like " record.data.postTemplate = (...) " but I got an infinite loop throwing an execption...
Can someone please advise? Also, if you need something else that could be useful for the answer let me know.
Thanks!
Out of the box the Associated objects are not serialized back to the server as you expect them . This issue has been brought up many times. The best thing might be to follow this thread:
http://www.sencha.com/forum/showthread.php?141957-Saving-objects-that-are-linked-hasMany-relation-with-a-single-Store
This thread talks about overriding getRecordData in the JSON writer class.

1 to many model association

I have problems to make an 1 to many model with Sencha Touch 2.
I want to save "persons" and add "todo's" to persons.
These values should be saved at the local storage.
So 1 person can have many todo's.
For this I have 2 models and 2 stores.
Personmodel:
Ext.define("app.model.PersonModel", {
extend: "Ext.data.Model",
config: {
idProperty: 'email',
fields: [
{ name: 'name', type: 'string' },
{ name: 'email', type: 'string' },
],
validations: [
{ type: 'presence', field: 'email' , message: 'Blabla'},
{ type: 'presence', field: 'name' , message: 'Blabla'},
{ type: 'email', field: 'email' , message: 'Blabla'},
]
}
});
TodoModel:
Ext.define("app.model.TodoModel", {
extend: 'Ext.data.Model',
config: {
idProperty: 'todoId',
fields: [
{ name: 'todoId', type: 'int' },
{ name: 'email', type: 'string' },
{ name: 'note', type: 'string' }
],
validations: [
{ type: 'presence', field: 'todoId', message: 'Blabla' },
{ type: 'presence', field: 'email', message: 'Blabla' },
{ type: 'presence', field: 'note', message: 'Blabla' }
]
}
});
PersonStore:
Ext.define("app.store.PersonStore", {
extend: "Ext.data.Store",
requires: "Ext.data.proxy.LocalStorage",
config: {
model: "app.model.PersonModel",
proxy: {
type: 'localstorage',
id: 'todo-app-personstore'
},
sorters: [{ property: 'name', direction: 'ASC'}],
grouper: {
sortProperty: "name",
direction: "ASC",
groupFn: function (record) {
}
}
}
});
TodoStore:
Ext.define("app.store.TodoStore", {
extend: "Ext.data.Store",
requires: "Ext.data.proxy.LocalStorage",
config: {
model: "app.model.TodoModel",
proxy: {
type: 'localstorage',
id: 'todo-app-todostore'
},
sorters: [{ property: 'email', direction: 'ASC'}],
grouper: {
sortProperty: "email",
direction: "ASC",
groupFn: function (record) {
}
}
}
});
I deleted the associations I made in the models because they didn't work at all.
Maybe relevant information: First I want to save a person. Later on I want to save todo's and connect them to a person.
Try Referring below links may helpful to you
http://miamicoder.com/2012/sencha-touch-2-models-hasmany-associations-php-example/
http://appointsolutions.com/2012/07/using-model-associations-in-sencha-touch-2-and-ext-js-4/

Extjs 4, Dynamic Tree and store re-mapping

I need to Extjs Tree panel with dynamic remote data(JSON) for file listing.
and the date field name is not fit to Extjs tree store field. so I need to re-mapping to make fit, like adding leaf field and text field.
the return JSON data is like this:
[{
"id":1,
"yourRefNo":"A91273",
"documentName":"Test Document",
"documentFileName":"login_to_your_account-BLUE.jpg",
"updatedBy":"root root",
"updatedAt":"\/Date(1343012244000)\/"
}]
and this is the tree panel:
Ext.define('App.view.Document.DocumentList', {
extend :'Ext.tree.Panel',
rootVisible : false,
alias: 'widget.Document_list',
store: 'DocumentList_store'
});
and this is the store:
Ext.define('App.store.DocumentList_store', {
extend: "Ext.data.TreeStore",
model: 'App.model.DocumentList_model',
proxy: {
type: 'ajax',
url: '/Document/GetDocumentList/',
actionMethods: {
read: 'POST'
},
reader: {
type: 'json',
root: '' // there is no root
},
pageParam: undefined,
startParam: undefined,
pageParam: undefined
},
root: {
children: []
},
autoLoad: false,
listeners: {
append: function (thisNode, newChildNode, index, eOpts) {
console.log(newChildNode.get('documentName')); // 'Test Document'
newChildNode.set('leaf', true);
newChildNode.set('text', newChildNode.get('documentName'));
// it does not add to tree panel.
}
}
});
after load data from server, and it call the append function well. but after that, nothing show up in tree panel.
What I am doing wrong? please advice me.
Thanks
[EDIT]
This is the model,
Ext.define("App.model.DocumentList_model", {
extend: "Ext.data.Model",
fields: [
'id','yourRefNo','documentName','documentFileName','updatedBy','updatedAt'
]
});
I'm fusing your code with a piece of working code of mine. Try see if this works:
Model:
Ext.define("App.model.DocumentList_model", {
extend: 'Ext.data.Model',
fields: [
{name: 'id'},
{name: 'yourRefNo'},
{name: 'documentName' },
{name: 'documentFileName'},
{name: 'updatedBy'},
{name: 'updatedAt', convert: function(v) { return v;} }, // Notice you can do field conversion here
{name: 'leaf', type: 'boolean', defaultValue: false, persist: false},
],
proxy: {
type: 'ajax',
url: '/Document/GetDocumentList/',
actionMethods: {
read: 'POST'
},
reader: {
type: 'json',
root: 'children'
},
},
});
Store:
Ext.define('App.store.DocumentList_store', {
extend: "Ext.data.TreeStore",
model: 'App.model.DocumentList_model',
root: {
text: 'Root',
id: null,
expanded: true
},
autoLoad: false,
});
JSON Response:
{
"success":true,
"children":[{
"id":1,
"yourRefNo":"A91273",
"documentName":"Test Document",
"documentFileName":"login_to_your_account-BLUE.jpg",
"updatedBy":"root root",
"updatedAt":"\/Date(1343012244000)\/",
"leaf":false
}]
}

Sencha Touch not reading data

I have my model as this:
Ext.define("NotesApp.model.Note", {
extend: "Ext.data.Model",
config: {
idProperty: 'id',
fields: [
{ name: 'id', type: 'int' },
{ name: 'dateCreated', type: 'date', dateFormat: 'c' },
{ name: 'question', type: 'string' },
{ name: 'answer', type: 'string' },
{ name: 'type', type: 'int'},
{ name: 'author', type: 'int'}
],
validations: [
{ type: 'presence', field: 'id' },
{ type: 'presence', field: 'dateCreated' },
{ type: 'presence', field: 'question', message: 'Please enter a question for this card.' }
]
}
});
and my server page (qa.php) outputs this:
{"results":[{"id":"1","dateCreated":"2012-05-01","question":"asdf?","answer":"fdsa","type":"0","author":"0"},{"id":"2","dateCreated":"2012-05-01","question":"qwer?","answer":"rewq","type":"0","author":"0"}]}
and this is my code in the store:
Ext.define("NotesApp.store.Online", {
extend: "Ext.data.Store",
config: {
model: 'NotesApp.model.Note',
storeId: 'Online',
proxy: {
type: 'jsonp',
url: 'http://xxxxxxxx.com/qa.php',
reader: {
type: 'json',
rootProperty: 'results'
}
},
autoLoad: false,
listeners: {
load: function() {
console.log("updating");
Ext.getStore('Notes').getProxy().clear();
console.log("updating1");
// Loop through records and fill the offline store
this.each(function(record) {
console.log("updating2");
Ext.getStore('Notes').add(record.data);
});
// Sync the offline store
Ext.getStore('Notes').sync();
console.log("updating3");
// Remove data from online store
this.removeAll();
console.log("updated");
}
},
fields: [
{
name: 'id'
},
{
name: 'dateCreated'
},
{
name: 'question'
},
{
name: 'answer'
},
{
name: 'type'
},
{
name: 'author'
}
]
}
});
But when I called Ext.getStore('Online').load(), the console showed "updating", "updating1", and "updating3" but not any "updating2", ie. no records were found. I wonder where the mistake is? Is there a way to output the jsonstring that's read in?
This is a different scope
listeners: {
load: function() {
console.log("updating");
Ext.getStore('Notes').getProxy().clear();
console.log("updating1");
// Loop through records and fill the offline store
this.each(function(record) {
console.log("updating2");
Ext.getStore('Notes').add(record.data);
});
// Sync the offline store
Ext.getStore('Notes').sync();
console.log("updating3");
// Remove data from online store
this.removeAll();
console.log("updated");
},
this//adds scope
or
listeners: {
load: function(store,record,options) {
console.log("updating");
Ext.getStore('Notes').getProxy().clear();
console.log("updating1");
// Loop through records and fill the offline store
store.each(function(record) {
console.log("record"); //wahei records!
Ext.getStore('Notes').add(record.data);
});
// Sync the offline store
Ext.getStore('Notes').sync();
console.log("updating3");
// Remove data from online store
this.removeAll();
console.log("updated");
}

Resources