i have json data like this
{"GetStudentDetails":
{"TotalCount":5,
"RootResults":[
{"city":"West Chester","country":"USA","state":"PA ","student_id":100},
{"city":"Philly","country":"USA","state":"PA","student_id":101},
{"city":"Buffalo","country":"USA","state":"NY","student_id":102},
{"city":"Naigra City","country":"USA","state":"NY","student_id":103},
{"city":"West Chester","country":"USA","state":"PA","student_id":104}]
}
}
How to get this data into a store?
i am trying using a model like this.
Ext.define('User', {
extend: 'Ext.data.Model',
fields: [
{ type: 'string', name: 'TotalCount' }
],
hasMany: [{ model: 'RootResults', name: 'RootResult'}]
});
Ext.define("RootResults", {
extend: 'Ext.data.Model',
fields: [
{ type: 'string', name: 'city' },
{ type: 'string', name: 'country' },
{ type: 'string', name: 'state' },
{ type: 'string', name: 'student_id' }
],
belongsTo: 'User'
});
var store = Ext.create('Ext.data.Store', {
model: 'User',
proxy: {
type: 'ajax',
url: 'users.json',
reader: {
type: 'json'
}
}
});
How should my model be? when i am giving some more simple json i am getting the store loaded. i think the problem is with mapping?
Define model as
Ext.define("RootResults", {
extend: 'Ext.data.Model',
fields: [
{ type: 'string', name: 'city' },
{ type: 'string', name: 'country' },
{ type: 'string', name: 'state' },
{ type: 'string', name: 'student_id' }
],
});
And inside the reader definition add two parameters:
root: 'GetStudentDetails.RootResults'
totalProperty: 'GetStudentDetails.TotalCount'
Something like that... Main idea - don't try to bring internal JSON structure to your model - it should be reader responsibility to properly parse it.
Related
I have a nested JSON and I cannot seem to extract the nested array. I am not sure if I set up my store and models correctly. It seems right. As you can see at the bottom of this post, when I try to get the nested part out, it doesn't work.
JSON data:
{
"data":{
"name":"John",
"age":"23",
"gender":"Male",
"purchase":[
{
"item":"shirt",
"qty":1,
"price":10
},
{
"item":"hat",
"qty":2,
"price":25
},
{
"item":"pants",
"qty":1,
"price":15
}
]
},
"success":true,
"errorMsg":""
}
Store:
Ext.define('Pvm.store.MyStore', {
extend: 'Pvm.store.PvmBaseStore',
requires: [
'Pvm.model.Customer'
],
model: 'Pvm.model.Customer',
autoLoad: false
});
Customer Model:
Ext.define('Pvm.model.Customer', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field',
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json'
],
fields: [{
name: 'name',
type: 'auto'
}, {
name: 'age',
type: 'auto'
}, {
name: 'gender',
type: 'auto'
}],
associations: {
type: 'hasMany',
model: 'Pvm.model.Purchase',
name: 'purchase',
associationKey: 'purchase'
},
proxy: {
type: 'ajax',
actionMethods: {
create: 'POST',
read: 'POST', // changed read's method to POST (from GET) so we get the parameters as form data (not in URL, for security reasons)
update: 'POST',
destroy: 'POST'
},
url: '/pvmsvr/uiapi?cmd=readXml',
reader: {
type: 'json',
rootProperty: 'data'
}
}
});
Purchase Model:
Ext.define('Pvm.model.Purchase', {
extend: 'Ext.data.Model',
requires: [
'Ext.data.Field',
'Ext.data.proxy.Ajax',
'Ext.data.reader.Json'
],
fields: [{
name: 'item',
type: 'auto'
}, {
name: 'qty',
type: 'auto'
}, {
name: 'price',
type: 'auto'
}],
associations: {
type: 'belongsTo',
model: 'Pvm.model.Customer'
}
});
Controller Code:
onStoreLoaded: function(store, records, successful, eOpts) {
console.log(store); // works
console.log(records); // works
console.log(records[0].get('name')); // works
console.log(records[0].purchase(); // doesn't work; returns 'undefined'
}
I am idiot. I needed the child model's class name in the parent's requires...
I'm bangin' my head against the wall in the last hours, and I can't figure out a solution to my problem. In my sails models, I have 2 one-to-many associations. 'A' model can have many 'B', and 'B' model can have many 'C'. In my controller, when I do a.find().populate('b') (...) it returns me the entire collection of A model, but populate each entry of A model with only one B, which doesn't match the current dataset I have in my database(mysql). And doesn't populate the C entries in the B model. In other words, I'm trying to achieve something like nested population.
It's something wrong with the Controller code, right? How can I make this work?
Thanks in advance!
EDIT:
Company.js
module.exports = {
identity: 'company',
attributes: {
name: {
type: 'string',
required: true
},
address: {
type: 'string',
required: true
},
zip_code: {
type: 'string',
required: true
},
city: {
type: 'string',
required: true
},
nif: {
type: 'integer',
required: true,
minLength: 9
},
country: {
type: 'string',
required: true
},
phone_number: {
type: 'string',
required: true
},
email: {
type: 'email',
required: true
},
facilities: {
collection: 'facility',
references: 'facility',
on: 'id',
via: 'company'
}
}
};
Facility.js
module.exports = {
identity: 'facility',
attributes: {
company: {
columnName: 'id_company',
model: 'company'
},
warehouses: {
collection: 'warehouse',
references: 'warehouse',
on: 'id',
via: 'facility'
},
name: {
type: 'string',
required: true
},
address: {
type: 'string',
required: true
},
zip_code: {
type: 'string',
required: true
},
city: {
type: 'string',
required: true
},
country: {
type: 'string',
required: true
},
phone_number: {
type: 'string',
},
email: {
type: 'email',
},
longitude: {
type: 'float',
},
latitude: {
type: 'float'
}
}
};
Warehouse.js
module.exports = {
identity: 'warehouse',
attributes: {
facility: {
columnName: 'id_facility',
model: 'facility',
},
name: {
type: 'string',
required: true
},
longitude: {
type: 'float',
},
latitude: {
type: 'float'
}
}
};
MainController's relevant code:
companies: function(req, res) {
company.find().populate('facilities').exec(function(err, comp){
var error = '';
if(err){
error = 'Unable to retrieve the requested information. Try again later and, if the problem persists, contact the platform administrator.';
} else if(!comp[0]) {
error = 'There\'s no company data inserted.';
}
// (...)
});
},
You should remove the references and on from your models.
Regarding nested population, just like I said in the comment, Waterline does not currently support it. You could check Waterline2 which, as they say, offers the possibility of nested populating, but is not recommended for production.
Otherwise you could check this out: Sails.js populate nested associations
I have a simple model, let's say:
Ext.define('UserModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'firstname', type: 'string'},
{name: 'lastname', type: 'string'}
]
});
And a json file that looks like this:
{
"DatabaseInJSON": {
"Users": [
{
"KeyFirstName": "John",
"KeyLastName": "Doe"
},{
"KeyFirstName": "James",
"KeyLastName": "Howlett"
}
],
"OtherStuffWeDontCareAbout": [
...
]
}
}
My question is:
If I create a store like this, how can i map the attribute "firstname" from my model to "KeyFirstName" from my json ?
Ext.define('my.custom.Store', {
extend: 'Ext.data.Store',
model: 'UserModel',
proxy: {
type: 'ajax',
url: 'path/to/my/file.json',
reader: {
type: 'json',
rootProperty: 'DatabaseInJSON'
}
}
});
You need to either employ mapping or a convert function
Have a look at the demo here which demonstrates both in action.
For the sake of the demo I turned your store into a memory proxy store and you are I presume also accessing your rootProperty wrong as it should be rootProperty: 'DatabaseInJSON.Users'
Code:
Ext.application({
name: 'Fiddle',
launch: function() {
myData = {
"DatabaseInJSON": {
"Users": [{
"KeyFirstName": "John",
"KeyLastName": "Doe"
}, {
"KeyFirstName": "James",
"KeyLastName": "Howlett"
}],
"OtherStuffWeDontCareAbout": {}
}
};
Ext.define('UserModel', {
extend: 'Ext.data.Model',
fields: [{
name: 'firstname',
mapping: 'KeyFirstName',
type: 'string'
}, {
name: 'lastname',
convert: function(v, record) {
return record.data.KeyLastName;
},
type: 'string'
}]
});
Ext.define('my.custom.Store', {
extend: 'Ext.data.Store',
model: 'UserModel',
proxy: {
type: 'memory',
reader: {
type: 'json',
rootProperty: 'DatabaseInJSON.Users'
}
}
});
myStore = Ext.create('my.custom.Store', {
data: myData
});
console.log(myStore.getRange());
}
});
Generally your Json properties should match the same names of your fields so that the reader can read them properly, to map 'KeyFirstName' to 'firstname' I think your best option would be to create a mapping in the field definition on the model.
This would apply this globally for all requests and I believe it would reverse the mapping when it come to saving the data.
To use the mapping in your case, you would need something like:
Ext.define('UserModel', {
extend: 'Ext.data.Model',
fields: [
{name: 'firstname', type: 'string', mapping: function(data) { return data.KeyFirstName; } },
{name: 'lastname', type: 'string', mapping: function(data) { return data.KeyLastName; } }
]
});
Other than changing the format of the JSON data, the only other way I can think of would be to override the read or getResponseData method of the JsonReader
Here is my model:
Ext.define('DynTabBar.model.Menu',{
extend: 'Ext.data.Model',
config: {
fields: [{
name: 'Title', type: 'string'
}, {
name: 'Level', type: 'int'
}, {
name: 'Parent', type: 'string'
}]
}
});
Store:
Ext.define('DynTabBar.store.MenuItems', {
extend: 'Ext.data.Store',
xtype: 'menustore',
config: {
storeId: 'menuStore',
model: 'DynTabBar.model.Menu',
autoLoad: false,
proxy: {
type: 'ajax',
id: 'menuproxy',
url: 'http://localhost:50567/api/Menu',
reader: {
type: 'json'
}
}
}
});
In controller I have smth like that:
var mainStore = Ext.getStore('menuStore');
mainStore.load();
My json respone from server is:
[{"Title":"home","Level":1,"Parent":""},{"Title":"home1","Level":2,"Parent":"home"},{"Title":"home2","Level":2,"Parent":"home"},{"Title":"info","Level":1,"Parent":""},{"Title":"info1","Level":2,"Parent":"info"},{"Title":"info2","Level":2,"Parent":"info"},{"Title":"info3","Level":2,"Parent":"info"}]
But store data is empty. What I'm missing or doing wrong?
I fixed the problem, the problem is that I'm not waiting while store data is loaded and do something while store isn't loaded. I fix that doing what I need in store loaded callback.
mainStore.load(callback);
I have the following JSON structure:
{
orderId : '00410',
name : 'Zuiger',
productionQuantity : '4',
materials : [
{
materialId : 'ALU.BALK.10X70',
description : 'Aluminium balk 10 x 70',
quantityPP : '70mm',
totalQuantity : '0.4'
},
{
materialId : 'ALU.BALK.10X70',
description : 'Aluminium balk 10 x 70',
quantityPP : '70mm',
totalQuantity : '0.4'
}],
operations : [
{
operationId : 'ZAGEN',
lineNr : '10',
description : 'Zagen groot',
started : false
},
{
operationId : 'FR003',
lineNr : '20',
description : 'Frezen Heidenhein',
started : true
}]
}
So i have an Order, which has a list of materials and/or a list of operations. This JSON is currently in a Store file using the Data tag and is autoLoaded. This is for testing purposes.
The model used for this is Order which contains 2 hasMany associations to material and operation:
Ext.define('wp-touch.model.Order', {
extend: 'Ext.data.Model',
requires: [
'wp-touch.model.Material',
'wp-touch.model.Operation'
],
config: {
idProperty: 'Id',
fields: [
{ name: 'orderId', type: 'string'},
{ name: 'name', type: 'string'},
{ name: 'productionQuantity', type: 'string'},
],
associations: [
{
type: 'hasMany',
associationKey: 'materials',
model: 'wp-touch.model.Material',
name: 'material',
primairyKey: 'materialId',
foreignKey: 'orderId'
},
{
type: 'hasMany',
associationKey: 'operations',
model: 'wp-touch.model.Operation',
name: 'operation',
primairyKey: 'operationId',
foreignKey: 'orderId'
}
],
}});
When the store is loaded it only loads the first hasMany. When i empty the materials array in the JSON message it loads in the operations just fine. So it seems it only loads one of the hasMany associations. Is there any way to fix this?
Here are the material and operation models;
Ext.define('wp-touch.model.Material', {
extend: 'Ext.data.Model',
config: {
idProperty: 'Id',
fields: [
{ name: 'materialId', type: 'string'},
{ name: 'description', type: 'string'},
{ name: 'quantityPP', type: 'string'},
{ name: 'totalQuantity',type: 'string'},
{ name: 'orderId', type: 'string'}
],
belongsTo: [
{
model: 'wp-touch.model.Order',
name: 'order',
primairyKey: 'materialId',
foreignKey: 'orderId'
}
]
}});
Ext.define('wp-touch.model.Operation', {
extend: 'Ext.data.Model',
config: {
idProperty: 'Id',
fields: [
{ name: 'operationId', type: 'string'},
{ name: 'lineNr', type: 'int'},
{ name: 'description', type: 'string'},
{ name: 'started', type: 'boolean'},
{ name: 'orderId', type: 'string'}
],
belongsTo: [
{
model: 'wp-touch.model.Order',
name: 'order',
primairyKey: 'operationId',
foreignKey: 'orderId'
}
]
}});