ExtJS load data to Form from Store with association - extjs

I have a single form that has fields for a Employee Model and fields for Person Model.
Employee Model
Ext.define('App.model.Employee', {
extend: 'Ext.data.Model',
fields: [{
name: 'EmployeeId',
type: 'int'
},
{
name: 'PersonId',
type: 'int'
},
'EmployeeNumber',
'JoinDate'
],
belongsTo: 'App.model.Person'
});
Person Model
Ext.define('App.mode.Person', {
extend: 'Ext.data.Model',
fields: [{
name: 'PersonId',
type: 'int'
},
'FirstName',
'LastName'
],
hasMany: {
model: 'App.model.Employee',
name: 'Employees'
}
});
My Store:
var store = Ext.create('Ext.data.Store', {
model: 'App.model.Employee',
autoLoad: false,
autoSync: true,
proxy: {
type: 'ajax',
api: {
read: 'api/employee/getemployee'
},
reader: {
type: 'json',
successProperty: 'success',
root: 'data',
messageProperty: 'message'
}
}
});
This is my actual JSON
"data": [{
"EmployeeId": 5,
"PersonId": 1,
"EmployeeNumber": 2001,
"JoinDate" : "",
"Person": {
"PersonId": 1,
"FathersLast": "SMITH",
"FirstName": "JOHN"
}
}],
My question is how does my json response (from server) should be structured in order to load store successful?

You can find explanation and sample code in Ext data package guide section "Loading Nested Data". Other example is in the heading of Association documentation. Both with sample JSON files showing the required structure.

After looking at your code and json structure i can recognize that each employee has a person object, so you need to correct your mapping. Instead of Defining hasMany relationship in person model, you should define hasOne relationship for person in employee.
hasOne: {
model: 'App.mode.Person',
name: 'Person'
}
Please try this out. Your json structure looks good.

Related

Saving data to a model with association hasMany does not work

I want to keep the information about posts to the user. Save turns. But at the output of the data on the posts no longer exists.
Why are not posts stored?
Fiddle: https://fiddle.sencha.com/#view/editor&fiddle/22mp
Ext.define('Post', {
extend: 'Ext.data.Model',
fields: [{
name: 'title',
type: 'string'
}]
});
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [{
name: 'name',
type: 'string'
}],
hasMany: 'Post'
});
var user = Ext.create('User', {
name: "user1"
});
user.posts().add({
title: 'Post 10'
});
user.posts().sync();
console.log(user.getData()); // There are no posts!
You have to use
user.getData({associated:true}); to get the associated data for more information please see the documentation.
https://docs.sencha.com/extjs/6.5.0/modern/Ext.data.Model.html#method-getData

Define mapping in reader

I have defined a custom ComboBox component, that I want to re-use with multiple Stores. It has a simple config as below.
Ext.define('Myapp.CustomCombo', {
extend: 'Ext.form.ComboBox',
valueField: 'id',
displayField: 'name'
});
The model is
Ext.define('Myapp.model.ComboModel',{
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' },
{ name: 'linkCls', type: 'string' }
]
});
I define multiple stores each with its own proxy config & identified by a unique storeId, as below
Ext.create('Myapp.store.EmployeeComboStore', {
model: 'Myapp.model.ComboModel',
storeId: 'employeeLOVComboStore',
proxy: {
type: 'rest',
url: '/employees/getLovData',
reader: {
type: 'json',
rootProperty: 'data'
}
}
});
The server responds with a json as below
{
"data" : [
{"employeeId": 1, "employeeName": "Chris"},
{"employeeId": 2, "employeeName": "Jack"},
]
}
I can have multiple such stores, like departmentStore with a different proxy URL and where in, the server response could be
{
"data" : [
{"departmentId": 1, "departmentName": "Sales"},
{"departmentId": 2, "departmentName": "Marketing"},
]
}
I want to define a mapping in the Reader, with instructions to map data differently in different stores, as in.. employeeId should be mapped to 'id' & employeeName to 'name' in employeeStore, whereas departmentId should be mapped to 'id' & departmentName to 'name' in departmentStore.
I've seen that there are options to define mapping for each field in a Model, but I would want to define a mapping in a Reader, since the server responds with data from a relational database where field names would be the columnNames.
What you can do, is to send along metaData from the server to the client.
The json response can look like this:
{
data: [{ ... }],
msg: "...",
total: 99,
metaData: {
fields: [{ ... }],
columns: [{ ... }],
idProperty: "id",
messageProperty: "msg",
root: "data"
}
}
In you case it would be sufficient if the json response would look like this
{
data: [{ ... }],
metaData: {
fields: [
{ name: 'Id', type: 'int', mapping: 'departmentId' },
{ name: 'Name', type: 'string', mapping: 'departmentName' },
]
}
}
Here is also a good example how it works: Basic Meta Data Config

Extjs hasOne association not loading preoperly

I have a Person model which has an Address associated to it via 'hasOne'. Both models load data via REST proxy. If I load a person and try to get the address I can see a http request to the url of the addresses but without any kind of person id in it so my server sends an error.
Person:
Ext.define('AP.model.Person', {
extend: 'Ext.data.Model',
fields: [
{ name: 'id', type: 'int', persist : false },
{ name: 'name', type: 'string' }
],
proxy: {
type: 'rest',
url : AP_ROOT_URL + 'persons/'
},
associations: [{
type: 'hasOne',
model: 'AP.model.Addresses',
foreignKey: 'person_id',
primaryKey: 'id',
getterName: "getAddress"
}]
});
Address:
Ext.define('AP.model.Address', {
extend: 'Ext.data.Model',
fields: [
{ name: 'person_id', type: 'int', persist : false },
{ name: 'address', type: 'string' }
],
proxy: {
type: 'rest',
url : AP_ROOT_URL + 'addresses/'
}
});
The following code:
person.getAddress(function(address){
console.log(address);
});
creates a request to:
http://localhost/addresses
when it should create a request to:
http://localhost/addresses/person_id (http://localhost/addresses/1)
What you have here is a HasMany relation, not HasOne. You won't get HasOne to work with these models because, as said in the docs: "the owner model is expected to have a foreign key which references the primary key of the associated model". In your case, the foreign key is in the associated model (which makes it a 1-n relationship).

Associations and class names

I tried to build a very simple application that creates a store based on two associated models. (It is based on an example you can find here.) This works if I use a shore class name. However, it does not work anymore as soon as I use the class name with the path and the application name, as I was used to do.
I made the following changes:
Changed "Pessoa" to "Aap.model.Pessoa"
Changed "Endereco" to "Aap.model.Endereco"
Could somebody please explain to me:
What is the underlying problem?
What do I have to change in order to make the assosiations work in the second example
Example that works
app.js:
Ext.Loader.setConfig({
enabled: true, // Allows dynamc loading of JavaSCript files
disableCaching: false // Disable random parameter in the URLs path});
Ext.application({
name: 'Aap',
models: ['Pessoa', 'Endereco']});
app/model/Pessoa.js:
Ext.define('Pessoa', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'nome', type: 'string'}
],
proxy: {
type: 'rest',
url: 'data/data',
format: 'json'
},
hasOne: {model: 'Endereco', foreignKey: 'pessoaId'} }
app/model/Endereco.js:
Ext.define('Endereco', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'logradouro', type: 'string'}
]});
data/data.json:
[
{
"id": 1,
"nome": "Loiane",
"sobrenome": "Groner",
"endereco": {
"id": 14,
"logradouro": "rua ficticia",
"numero": "100"
}
},
{
"id": 2,
"nome": "Tom",
"sobrenome": "Stock",
"endereco": {
"id": 34,
"logradouro": "reality street",
"numero": "55"
}
}]
Command in the browser console:
pessoaStore = new Ext.data.Store({
autoLoad: true,
model: 'Pessoa'
});
As a result I get a store with two properly associated model. If I change the class name, however, association does not work anymore.
Example that does not work
app.js:
Ext.Loader.setConfig({
enabled: true, // Allows dynamc loading of JavaSCript files
disableCaching: false // Disable random parameter in the URLs path});
Ext.application({
name: 'Aap',
models: ['Aap.model.Pessoa', 'Aap.model.Endereco']});
app/model/Pessoa.js:
Ext.define('Aap.model.Pessoa', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'nome', type: 'string'}
],
proxy: {
type: 'rest',
url: 'data/data',
format: 'json'
},
hasOne: {model: 'Aap.model.Endereco', foreignKey: 'pessoaId'} }
app/model/Endereco.js:
Ext.define('Aap.model.Endereco', {
extend: 'Ext.data.Model',
fields: [
{name: 'id', type: 'int'},
{name: 'logradouro', type: 'string'}
]});
data/data.json:
[
{
"id": 1,
"nome": "Loiane",
"sobrenome": "Groner",
"endereco": {
"id": 14,
"logradouro": "rua ficticia",
"numero": "100"
}
},
{
"id": 2,
"nome": "Tom",
"sobrenome": "Stock",
"endereco": {
"id": 34,
"logradouro": "reality street",
"numero": "55"
}
}]
Command in the browser console:
pessoaStore = new Ext.data.Store({
autoLoad: true,
model: 'Aap.model.Pessoa'
});
Here I get as a result the store with the data of the "Pessoa" model, but the "Endereco" model is not associated and I cannot get the corresponing data.
Any help is appreciated!
I figured out the problem:
In the "app/model/Pessoa.js file" I simply had to replace
hasOne: {model: 'Endereco', foreignKey: 'pessoaId'}
to
hasOne: {model: 'Aap.model.Endereco', associationKey: 'endereco', foreignKey: 'pessoaId'}
Now, the associaiton is working correctly.
The problem the associationKey, which is the property to read the association from. As explained in the ExtJS dcumentation the associationKey is by default the name of the associated moel.
In the first example (the one that worked), this worked well. The associationKey was correspondinly to the model name "Endereco" set to "endereco" by default.
In the second example (the one that did not work), however, the default associationKey did not find any property in the data (app/model/Pessoa.js) with the same name. The associationKey was correspondinly to the model name "Aap.model.Endereco" set to "aap.model.endereco" by default.
The associationKey had therefore to be defined explicitely as "endereco" in order to solve the problem.

ExtJS 4.1 - Nested hasOne associated in JSON

I have JSON in the following format:
{
"id": 1,
"arbitraryAttribute": "arbitraryValue",
"thing": {
"thingKey1": "thingValue1",
"thinkKey2": "thingValue2"
}
}
This model is represented like so:
Ext.define("MyModel", {
extends: "Ext.data.Model",
fields: [
{name: "id", type: "string"},
{name: "arbitraryAttribute", type: "string"},
],
hasOne: [
{
model: "Thing",
name: "thing"
}
]
});
Ext.define("Thing", {
extends: "Ext.data.Model",
fields: [
{name: "thingKey1", type: "string"},
{name: "thingKey2", type: "string"}
]
});
The proxy is a simple json proxy. The JSON it is getting looks like that which I presented, but my record seems to have no knowledge of the Thing model. Is there any additional plumbing I need to set up to get MyModel to pull the nested Thing json?
Your forgot to set the thing_id in MyModel. Also this doesnt work at all in ExtJs.
You can now set the thing_id via JSON but not the whole object as you do (and it should).
It will autoLoad the complete object via the models proxy if required.
Ext.define('User', {
extend:'Ext.data.Model',
fields: ['id', 'name', 'status'],
associations: [
{ type: 'hasOne', model: 'Status', associationKey: 'status' }
]
});
Ext.define('Status', {
extend:'Ext.data.Model',
fields: ['id', 'title'],
});
Demo here

Resources