-
4 Sep 2012 5:25 AM #1
Answered: Calculated field in model
Answered: Calculated field in model
Hello all,
I have a model with different fields that are based on other fields. I thought I can use the convert function but that is only called at the first time. So it returns the value from the beginning en it's not calculated with changed data in the store. What kind of solutions are possible? Do I have to create a function in the model that update the calculated fields?
I hope somebody knows the trick or can give me some good advice.PHP Code:fields: [
{
name: 'FieldA'
},
{
name: 'FieldB' //editable in grid, default is 0
},
{
name: 'FieldC' // is A * B
convert: function(v, record){
return record.data.FieldA * record.data.FieldB; // FieldB is always 0 here
}
}
]
//maybe a function?
updateCalculatedFields: function() {
this.set('FieldC', this.get('FieldA') * this.get('FieldB') );
}
Thanks!
-
Best Answer Posted by vietits
According to source code of Ext.data.Model, value of converted field will only be calculated and updated when you create a record from Model or set value to that field. So in your case, before getting value of converted field, you should set it to some value.
Code:onRawMaterialsGridEdit: function(editor, e, options) { e.record.set('Total', (e.record.getData().Price / 1000) * e.record.getData().Quantity ); this.getRawMaterialsTotal().setValue(e.grid.store.sum('Total')); console.log('Quantity: '+e.record.get('Quantity')); //output: 500 console.log('StraightElementNNO3Percentage: '+e.record.get('StraightElementNNO3Percentage')); //output:13% e.record.set('StraightElementNNO3'); console.log('StraightElementNNO3: '+e.record.get('StraightElementNNO3')); },
-
4 Sep 2012 5:55 AM #2Sencha - Community Support Team
- Join Date
- May 2012
- Location
- Istanbul
- Posts
- 1,331
- Vote Rating
- 77
- Answers
- 124
Hi,
you can use following code:
you can use renderer to particular column
Code:Ext.define('User', { extend: 'Ext.data.Model', fields: [ {name: 'a'}, {name: 'b'}, {name: 'c'}, ] }); Ext.create('Ext.data.Store', { storeId:'simpsonsStore', model:'User', data:{'items':[ { 'a': '2', "b":"5", "c":"0" }, { 'a': '3', "b":"6", "c":"0" }, { 'a': '4', "b":"5", "c":"0" }, { 'a': '4', "b":"8", "c":"0" } ]}, proxy: { type: 'memory', reader: { type: 'json', root: 'items' } } }); Ext.create('Ext.grid.Panel', { title: 'Simpsons', store: Ext.data.StoreManager.lookup('simpsonsStore'), columns: [ { text: 'A', dataIndex: 'a' }, { text: 'B', dataIndex: 'b',editor:'textfield' }, { text: 'C', dataIndex: 'c',renderer:function(value,metadata,record){ return parseInt(record.get('a'))*parseInt(record.get('b')); } } ], selType: 'rowmodel', plugins: [ Ext.create('Ext.grid.plugin.RowEditing', { clicksToEdit: 1 }) ], height: 200, width: 400, renderTo: Ext.getBody() });sword-it.com, Sencha Developer House in Turkey - Istanbul University Technopark Suite 204.
-
4 Sep 2012 6:01 AM #3
Thanks you for the fast response!

I need also sum of the calculated fields, so a thought using Ext.getStore('store').sum('calculatedField');
In you're case this is not possible, I'm only showing the total of this calculated fields.
I hope you understand what I mean.
Thanks
-
4 Sep 2012 6:22 AM #4Sencha - Support Team
- Join Date
- Jul 2010
- Location
- Houston, Tx
- Posts
- 7,190
- Vote Rating
- 195
- Answers
- 436
You can use converted fields:
Scott.Code:Ext.onReady(function () { Ext.define('TestResult', { extend: 'Ext.data.Model', fields: [ 'student', { name: 'month1', type: 'int' }, { name: 'month2', type: 'int' }, { name: 'total', type: 'int', convert: function(val,row) { return row.data.month1 + row.data.month2; } } ] }); var cellEditing = Ext.create('Ext.grid.plugin.CellEditing', { clicksToEdit: 1, listeners: { beforeedit: function(e,opts) { //console.log(e); console.log(opts); // opts.record.data.field to get field record value of data in row }, edit: function(editor,e,opts){ console.log(e.value); // new value; update store; also see e.record object } } }); Ext.create('Ext.grid.Panel', { width: 500, height: 140, renderTo: document.body, features: [{ ftype: 'summary' }], store: { model: 'TestResult', data: [{ student: 'Row 1', month1: 100, month2: 50 },{ student: 'Row 2', month1: 200, month2: 100 },{ student: 'Row 3', month1: 300, month2: 150 } ] }, columns: [{ dataIndex: 'student', text: 'Name', summaryType: 'count', summaryRenderer: function(value, summaryData, dataIndex) { return Ext.String.format('{0} row{1}', value, value !== 1 ? 's' : ''); } }, { dataIndex: 'month1', text: 'Month1', summaryType: 'sum', editor: { xtype: 'numberfield' } }, { dataIndex: 'month2', text: 'Month2', summaryType: 'sum', editor: { xtype: 'numberfield' } }, { dataIndex: 'total', text: 'total', summaryType: 'sum' } ], plugins: [cellEditing] }); });
-
4 Sep 2012 9:54 AM #5
Whats wrong?
Whats wrong?
Thanks for the reply, I'm trying to using the convert function but I'm stuck. Here are some code snippets.
The model
And next the edit event functionPHP Code:{
name: 'Quantity',
type: 'int'
},
{
name: 'Total'
},
{
name: 'DensityInLiters'
},
{
name: 'StraightElementNNO3Percentage',
type: 'int'
},
{
name: 'StraightElementNNO3',
type: 'float',
convert: function(val, row){
return row.data.Quantity/1000*row.data.StraightElementNNO3Percentage;
}
},
The convert function is not called when I user e.record.get so it returns the old value and that is zero. I think I forget something?PHP Code:onRawMaterialsGridEdit: function(editor, e, options) {
e.record.set('Total', (e.record.getData().Price / 1000) * e.record.getData().Quantity );
this.getRawMaterialsTotal().setValue(e.grid.store.sum('Total'));
console.log('Quantity: '+e.record.get('Quantity')); //output: 500
console.log('StraightElementNNO3Percentage: '+e.record.get('StraightElementNNO3Percentage')); //output:13%
console.log('StraightElementNNO3: '+e.record.get('StraightElementNNO3')); //output: 0
},
Thanks!
-
4 Sep 2012 10:25 PM #6
still not succeeded
still not succeeded
I'm still not succeeded, who knows what I'm doing wrong?
Thanks
-
4 Sep 2012 11:15 PM #7
According to source code of Ext.data.Model, value of converted field will only be calculated and updated when you create a record from Model or set value to that field. So in your case, before getting value of converted field, you should set it to some value.
Code:onRawMaterialsGridEdit: function(editor, e, options) { e.record.set('Total', (e.record.getData().Price / 1000) * e.record.getData().Quantity ); this.getRawMaterialsTotal().setValue(e.grid.store.sum('Total')); console.log('Quantity: '+e.record.get('Quantity')); //output: 500 console.log('StraightElementNNO3Percentage: '+e.record.get('StraightElementNNO3Percentage')); //output:13% e.record.set('StraightElementNNO3'); console.log('StraightElementNNO3: '+e.record.get('StraightElementNNO3')); },
-
5 Sep 2012 1:00 AM #8
It works!
It works!
Thank you! It works!


-
6 Sep 2012 5:51 AM #9
It works but slow
It works but slow
Hello,
Unfortunately I have to reopen this thread because calculating the fields in the model is too slow.
I have a grid with one editable column after edit this column there are approximately 20 fields in the model that need to be updated. At this time one change takes 4 seconds in IE and 3 seconds in chrome...
Is there anyway to speed this up? I hope someone knows the trick because I don't like to use server side calculation...PHP Code://Controller, afteredit function
onRawMaterialsGridEdit: function(editor, e, options) {
e.record.updateCalculatedFields(); //update calculated fields in model, see below for model
this.getRawMaterialsTotal().setValue(e.grid.store.sum('Total')); //set the total to displayfield
}
//Model updateCalculatedFields
updateCalculatedFields: function(){
this.set('Total'); this.set('StraightElementNNO3'); this.set('StraightElementNNH4');
this.set('StraightElementNNH2'); this.set('StraightElementNtotal'); this.set('StraightElementP205');
this.set('StraightElementK2O'); this.set('StraightElementMgO'); this.set('StraightElementSO3');
this.set('StraightElementCl'); this.set('TraceElementFePPM'); this.set('TraceElementFePercentage');
this.set('TraceElementMnPPM'); this.set('TraceElementMnPercentage'); this.set('TraceElementZnPPM');
this.set('TraceElementZnPercentage');this.set('TraceElementCuPPM');
this.set('TraceElementCuPercentage');this.set('TraceElementBPPM');
this.set('TraceElementBPercentage');this.set('TraceElementMoPPM');
this.set('TraceElementMoPercentage');
}
//fields snippet
{
name: 'StraightElementNNO3Percentage',
type: 'int'
},
{
name: 'StraightElementNNO3',
type: 'float',
convert: function(val, row){
return row.data.Quantity/1000*row.data.StraightElementNNO3Percentage;
}
},
},
Thanks!
-
6 Sep 2012 6:13 AM #10Sencha - Support Team
- Join Date
- Jul 2010
- Location
- Houston, Tx
- Posts
- 7,190
- Vote Rating
- 195
- Answers
- 436
I am not sure why you would make this statement.because I don't like to use server side calculation...
My suggestion would be to create a view to calculate the data and simply return the result. The server's job is to manage the data and display the result to the client. Many slowdowns are created by trying to calculate data at the client during rendering.
This aside, You could try to create a function to calc the data and update the store before displaying it to the grid. I have not tried to benchmark this as I let the server do all of the work .. as it should.
Regards,
Scott.


Reply With Quote