1. #1
    Touch Premium Member
    Join Date
    Nov 2011
    Posts
    125
    Vote Rating
    0
    Answers
    1
    JavascriptParrot is on a distinguished road

      0  

    Question 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?

    PHP Code:
    fields: [
    {
        
    name'FieldA'
    },
    {
        
    name'FieldB' //editable in grid, default is 0
    },
    {
        
    name'FieldC' // is A * B
       
    convert: function(vrecord){
             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') );

    I hope somebody knows the trick or can give me some good advice.

    Thanks!

  2. 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'));     
    },

  3. #2
    Sencha - Community Support Team sword-it's Avatar
    Join Date
    May 2012
    Location
    Istanbul
    Posts
    1,333
    Vote Rating
    85
    Answers
    124
    sword-it is a jewel in the rough sword-it is a jewel in the rough sword-it is a jewel in the rough sword-it is a jewel in the rough

      0  

    Default


    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. #3
    Touch Premium Member
    Join Date
    Nov 2011
    Posts
    125
    Vote Rating
    0
    Answers
    1
    JavascriptParrot is on a distinguished road

      0  

    Default


    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

  5. #4
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,154
    Vote Rating
    475
    Answers
    685
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      1  

    Default


    You can use converted fields:

    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]
        });
    
        
    });
    Scott.

  6. #5
    Touch Premium Member
    Join Date
    Nov 2011
    Posts
    125
    Vote Rating
    0
    Answers
    1
    JavascriptParrot is on a distinguished road

      0  

    Default 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
    PHP Code:
    {
                
    name'Quantity',
                
    type:  'int'
            
    },
            { 
               
    name'Total' 
           
    },
            { 
               
    name'DensityInLiters' 
           
    },        
           {
                
    name'StraightElementNNO3Percentage',
                
    type'int'
            
    },
            {
                
    name'StraightElementNNO3'
               
    type'float',
                
    convert: function(valrow){
                    return 
    row.data.Quantity/1000*row.data.StraightElementNNO3Percentage;
                }
            }, 
    And next the edit event function
    PHP Code:
     onRawMaterialsGridEdit: function(editoreoptions) {
           
    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    
    }, 
    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?

    Thanks!

  7. #6
    Touch Premium Member
    Join Date
    Nov 2011
    Posts
    125
    Vote Rating
    0
    Answers
    1
    JavascriptParrot is on a distinguished road

      0  

    Default still not succeeded

    still not succeeded


    I'm still not succeeded, who knows what I'm doing wrong?

    Thanks

  8. #7
    Sencha - Community Support Team
    Join Date
    Jan 2012
    Posts
    1,376
    Vote Rating
    115
    Answers
    346
    vietits is a splendid one to behold vietits is a splendid one to behold vietits is a splendid one to behold vietits is a splendid one to behold vietits is a splendid one to behold vietits is a splendid one to behold

      1  

    Default


    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'));     
    },

  9. #8
    Touch Premium Member
    Join Date
    Nov 2011
    Posts
    125
    Vote Rating
    0
    Answers
    1
    JavascriptParrot is on a distinguished road

      0  

    Default It works!

    It works!


    Thank you! It works!

  10. #9
    Touch Premium Member
    Join Date
    Nov 2011
    Posts
    125
    Vote Rating
    0
    Answers
    1
    JavascriptParrot is on a distinguished road

      0  

    Default 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...

    PHP Code:
    //Controller, afteredit function
    onRawMaterialsGridEdit: function(editoreoptions) {
        
    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(valrow){
                    return 
    row.data.Quantity/1000*row.data.StraightElementNNO3Percentage;
                }
            },
         }, 
    Is there anyway to speed this up? I hope someone knows the trick because I don't like to use server side calculation...

    Thanks!

  11. #10
    Sencha - Support Team scottmartin's Avatar
    Join Date
    Jul 2010
    Location
    Houston, Tx
    Posts
    9,154
    Vote Rating
    475
    Answers
    685
    scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future scottmartin has a brilliant future

      0  

    Default


    because I don't like to use server side calculation...
    I am not sure why you would make this statement.
    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.