ExtJs json response custom transformation to store model - javascript

I use ExtJs 4.1.3 and have the following scenario:
1. ExtJs grid which use some store with model
//model
Ext.define('MyApp.model.Tariff', {
extend: 'Ext.data.Model',
fields: [
{
name: 'country',
type: 'string'
},
{
name: 'tariff',
type: 'string'
}
]
});
//grid
var tariffsGrid = Ext.create('Ext.grid.Panel', {
id: 'tariffsGridId',
title: 'Tariffs',
store: tariffsStore,
columns: [
{ text: 'Country', dataIndex: 'country' },
{ text: 'Tariff', dataIndex: 'tariff' }
]
});
2. Http api which returns json
{
countries: [...],
tariffs: [..]
}
I want to get this json with ajax request and transform it according to some logic to the array of model MyApp.model.Tariff.
How I can correctly implement this ?
I have two ideas:
Make custom reader (extend: 'Ext.data.reader.Json') and use it for proxy in store
Override load method of the store and use Ext.Ajax.request
Which design is better and please post example of the implementation.

Related

ExtJS 5: Parent model convert dependency on Child association

I have 2 models... a Parent and a Child... a Parent hasMany Child models. In the Child, I have a field that is created by using its data (in this example, it's just converting and returning 1). In the Parent, I have two conversions going on... one uses its data, and the 2nd one depends on the Child's data. However, when creating the Parent model, it appears the Child association isn't fully baked yet, but when I go to update the Parent model with a new value, the Child association is there.
Basically, what I want to know is, when you see the Total2 console firing, I want Test to be populated. How do I force the associations to be read before using my conversion functions in the parent? And ideally, if there's a change in the Child, the dependent conversion function in Parent will automatically fire... I realize that most likely won't be possible, but it would be an incredible added bonus.
Here's my example.
app.js
Ext.application({
name : 'Fiddle',
launch : function() {
var store = Ext.create('Ext.data.Store', {
model: 'Namespace.model.Parent',
autoLoad: true,
listeners: {
load: onLoadStore
}
});
var grid = Ext.create('Ext.grid.Panel', {
title: 'associations',
store: store,
renderTo: Ext.getBody(),
columns: [{
text: 'Primary Key',
dataIndex: 'PrimaryKey'
}]
});
function onLoadStore(store, records, successful, eOpts) {
var firstGroups = store.first().getGroupsStore();
console.log('before', firstGroups.getCount(), firstGroups.isLoaded());
firstGroups.first().set('GroupName', 'blah');
store.first().set('blank', 1)
}
}
});
Parent
Ext.define('Namespace.model.Parent', {
extend: 'Ext.data.Model',
alias: 'model.parent',
requires: [
'Ext.data.field.Integer',
'Ext.data.field.String',
'Namespace.model.Child'
],
idProperty: "PrimaryKey",
fields: [{
type: 'string',
name: 'PrimaryKey',
critical: true
}, {
type: 'string',
name: 'Title'
}, {
type: 'int',
name: 'Rating',
defaultValue: 2
}, {
type: 'int',
name: 'Total',
depends: ['Rating'],
convert: function(value, record) {
console.log('Total', record)
return record.get('Rating') * 2;
}
}, {
name: 'Total2',
type: 'int',
depends: ['groupsMapping', 'blank'],
// depends on child's Test property
convert: function(value, record) {
var groupsMapping = record.get('groupsMapping');
if (groupsMapping) {
for (var i = 0; i < groupsMapping.length; i++) {
console.log('Total2', groupsMapping[i].GroupName, groupsMapping[i].Test);
}
}
return 0;
}
}, {
name: 'groupsMapping',
type: 'auto',
mapping: 'Groups'
}, {
name: 'blank',
type: 'int'
}],
hasMany: [{
model: 'Namespace.model.Child',
associationKey: 'Groups',
name: 'getGroupsStore'
}],
proxy: {
type: 'ajax',
url: 'data1.json'
}
});
Child
Ext.define('Namespace.model.Child', {
extend: 'Ext.data.Model',
alias: 'model.child',
fields: [{
type: 'int',
name: 'GroupInt',
critical: true
}, {
type: 'string',
name: 'GroupName'
}, {
name: 'Test',
type: 'int',
depends: ['GroupName'],
convert: function() {
console.log('Test, parent depends on this')
return 1;
}
}],
proxy: {
type: 'memory'
}
});
I've hit the same problem and took me some time in order to realise that the associations are not available on conversion time
Like in your example, I was sending the child records together with the parent ones (nested) and have 'manually' built a fake store using child model & parent field child data in order to do my math for the conversion / calculation, which did the trick:
{
name: 'validationScore',
depends: ['childRecords'],
type: 'number',
persist: false,
convertOnSet: true,
convert: function(val, rec){
// here we have access only to direct record field, and not the association association !
// we can use data directly in the calculation
children = rec.get('childRecords');
// or build a fake store in order to easily parse them
children = Ext.create('Ext.data.Store', {
model: 'Namespace.model.ChildModel',
data: rec.get('childRecords')
})
// ... calculate whatever
return result;
}
}
But now my 'new' challenge is to figure it out a (good) solution to update the converted value upon child records' changes ...
I did something similar to qdev, except I listened on the actual association's store. There's something funky about the constructor though... if I didn't put that timeout in there, then I would get an error with trying to access the first record in the store load... might be a framework bug, or I'm doing something terrible. The important code is the constructor and calculate method... in the app, I just have a 1 second timeout on changing the child data... you can see the grid's row data change from 3 to 102. Here's an updated example:
constructor: function(config) {
this.callParent(arguments);
var me = this;
setTimeout(function() {
var groupsStore = me.getGroupsStore();
if (groupsStore) {
groupsStore.on('update', me.calculateChanges, me);
groupsStore.on('datachanged', me.calculateChanges, me);
}
me.calculateChanges();
}, 1);
},
calculateChanges: function() {
console.log('calculating');
var groupsStore = this.getGroupsStore();
if (groupsStore) {
var total2 = 0;
groupsStore.each(function(group) {
total2 += group.get('Test');
});
this.set('Total2', total2);
}
},

How to filter from a combobox in Sencha-touch?

I am trying to filter in a combobox under Sencha Touch framework but I am not loading correct the records in the list.
My code is:
onTemplatesFilterChoosen: function(field, newValue, oldValue){
var store = Ext.getStore('Customers'),
templatesStore = store.getAt(0).templates(), //get the associated store
text = field.getRecord().data.text;
templatesStore.clearFilter();
//here the code to filter main store based in records of the associated store
}
But it is not working correctly and my store.getCount()for example is 0, showing a empty list.
In my main model I am adding a new model based in the properties of the filter called "CustomerTemplateModel"
associations: [
{
type: 'hasMany',
associatedModel: 'x.customer.model.CustomerTemplateModel',
ownerModel: 'x.customer.model.CustomerModel',
associationKey: 'templates',
autoLoad: true,
filterProperty: 'value',
name: 'templates'
}
]
And here the model associated:
Ext.define('x.customer.model.CustomerTemplateModel', {
extend: 'Ext.data.Model',
requires:[
],
config: {
useCache: false,
rootProperty: 'templates',
fields: [
{
name: 'text',
type: 'string'
},
{
name: 'value',
type: 'string'
}
]
}
});
What am I doing wrong??
Thank you in advance.

ExtJS grid not showing store data

My ExtJS Grid is not showing my store data. Using ExtJS 5
This is my grid (it's within a hbox):
{
xtype: 'grid',
title: 'Company Manager',
id: 'companyGrid',
flex: 1,
plugins: 'rowediting',
columnLines: true,
store: Ext.data.StoreManager.lookup('companyStore'),
columns: {
items: [{
header: 'ID',
dataIndex: 'id',
},
{
header: 'Name',
dataIndex: 'name',
},
{
header: 'Token',
dataIndex: 'access_token'
},
]
}
}
This is my store (I use the Google Extension of Sencha and it's filled with my data so this works + the ending }); were ignored by the coding block):
var companyStore = Ext.create('Ext.data.Store', {
storeId: 'companyStore',
proxy: {
type: 'ajax',
url: 'resources/data/company.json',
reader: {
type: 'json',
rootProperty: 'data'
}
},
fields: [{
name: 'id',
type: 'int'
}, {
name: 'name',
type: 'string'
}, {
name: 'access_token',
type: 'string'
}],
autoLoad: true
});
Does anyone know were I went wrong here?
I have tried: Reloading the store, checking if the store is actually filled, refreshing the grid view.
Nothing I tried worked and I decided to ask you guys for advice :)
#Evan Trimboli
You made me think and I fiddled arround for a second and found the following solution.
Instead of using the
store : Ext.data.StoreManager.lookup('companyStore'),
I used
bind : '{companyStore}',
And moved the define store towards the CompanyModel.js file :) now it works properly!!!!
Thanks :D

ExtJs Ext.grid.Panel access model from column

In Ext.grid.Panel when user changes checkbox's state, I need to save the model that represents this row.
I have this code (very simplistically, because this component is very big):
Ext.define('Hts.Appointments.List.Grid', {
extend : 'Ext.grid.Panel',
initComponent : function() {
this.store = /* Big initialization code for store */
this.columns = [{
header: Hts.Localization.APPOINTMENTS.HIGHLIGHT,
dataIndex: 'highlighted',
xtype: 'checkcolumn',
flex: 1,
listeners: {
checkchange: function(column,rowIndex,checked) {
/* Here I need to access the model and save it */
}
},
/* other columns */
]
}
})
I hope I provided enough information (I'm very new in ExtJs).
define your model with an id, using property 'idProperty'.
Ext.define('Model', {
extend: 'Ext.data.Model',
idProperty: 'idProp',
fields: [
{ name: 'id', type: 'int' },
{ name: 'name', type: 'string' }
]
});
you can get the model and save it with:
listeners: {
checkchange: function(column,rowIndex,checked) {
var model = Ext.ModelManager.getModel('idProp'); // access
model.save(); //save
}
},

get a row from a grid ExtJs 4

I think it's very simple to answer to this question:
I have simple grid with my custom store:
//other code
{
xtype: 'grid',
store: 'SecondStore',
itemId: 'mainTabPanel2',
columns: [
//this is not from the store
{
header: 'Not Form Store',
id: 'keyId2',
},
//from the store
{
header: 'From Store',
dataIndex: 'label',
id: 'keyId',
}
]
}
the store only populate the second column with id: keyId. In fact it have:
fields: [{ name: 'label' }]
And this work well.
I want to get from a function the row n°1 of this grid.
handler: function() {
var grid = Ext.ComponentQuery.query('grid[itemId="mainTabPanel2"]')[0];
//var row= get row(1) <- i don't know how to get the complete row
}
I'm working with ExtJs 4 so i can't get it with the command grid.getView().getRow(1);
I can't get it from the store because i want to get also the content of the column with id:keyId2 that is not stored in the store, so I can't do something like:
grid.getStore().getAt(1);
Anyone know how to get the complete row in ExtJs 4?
Thank you!
You can solve in this ExtJS 4.x using getNode: grid.getView().getNode(index)
getNode can take an HTML ID (not very useful), an index, or a store record.
I think you need something like this:
Ext.onReady(function () {
var store = Ext.create('Ext.data.Store', {
storeId: 'simpsonsStore',
fields: ['name', 'email', 'phone'],
data: {
'items': [{
'name': 'Lisa',
"email": "lisa#simpsons.com",
"phone": "555-111-1224"
}, {
'name': 'Bart',
"email": "bart#simpsons.com",
"phone": "555-222-1234"
}, {
'name': 'Homer',
"email": "home#simpsons.com",
"phone": "555-222-1244"
}, {
'name': 'Marge',
"email": "marge#simpsons.com",
"phone": "555-222-1254"
}]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
root: 'items'
}
}
});
var grid = Ext.create('Ext.grid.Panel', {
title: 'Simpsons',
store: Ext.data.StoreManager.lookup('simpsonsStore'),
columns: [{
text: 'Name',
dataIndex: 'name'
}, {
text: 'Email',
dataIndex: 'email',
flex: 1
}, {
text: 'Phone',
dataIndex: 'phone'
}],
height: 200,
width: 400,
renderTo: Ext.getBody()
});
alert(grid.getStore().getAt(1).data.name);
});
jsFiddle: http://jsfiddle.net/RftWF/
Get FireBug plugin and monitor the grid at 'handler'. If you see the data from the column keyId2 than you can see the way in the firebug too. i.e grid object->store object-> data array.
Can you tell us how did you add data in the column keyId2 of the grid ?
I've solved accesing the DOM:
/* Get Dom of the first grid */
var DOMgrid = Ext.select('#'+gridview.getId());
var gridChild = DOMgrid.elements[0].children[1].children[0].children;
Then you should get the "children" you are interested to simply following the DOM structure.
You can also get the singleton flyweight element applying the Ext.fly() comand and update the content with the update() comand:
Ext.fly(/*DOM object here*/).update(/*raw content here*/)

Categories

Resources