-
22 May 2012 12:41 AM #1
[4.1] Convert function in Ext.data.field not always invoked
[4.1] Convert function in Ext.data.field not always invoked
REQUIRED INFORMATION
Ext version tested:- Ext 4.1.0
- Ext 4.1.1 rc1
Browser versions tested against:- Firefox 11
- IE9
DOCTYPE tested against:- <!DOCTYPE html>
Description:- I have a model field with a convert function behind. If I load the data from service (Ext.Direct) everything works fine until now. But if I add or update a record to/in the store the convert function isn't invoked. If I query this store locally the field with convert function shows in case of an update the old value and in case of a new record added '0.'.
Steps to reproduce the problem:- See code below.
The result that was expected:- invoked convert function like in Ext 4.0.7
The result that occurs instead:- function isn't invoked or underlying fields do not return updated values.
Test Case:
Code:// ---------DATA ------------- var data = { themengebiete: [ { id: 1, pos: 1, themengebietname: 'Gebiet A' }, { id: 2, pos: 2, themengebietname: 'Gebiet B' } ] }; // --------- MODEL ------------- Ext.define('Iks.model.Themengebiet', { extend: 'Ext.data.Model', fields: [ { name: 'id', type: 'int' }, { name: 'pos', type: 'int' }, { name: 'themengebietname', type: 'string' }, { name: 'posAndThemengebietname', persist: false, convert: function (v, record) { return record.data.pos + '. ' + record.data.themengebietname; } } ], proxy: { type: 'memory', reader: { type: 'json', root: 'themengebiete' } } }); // --------- STORE ------------- Ext.define('Iks.store.Themengebiet', { extend: 'Ext.data.Store', storeId: 'Themengebiet', model: 'Iks.model.Themengebiet', autoLoad: true, data: data }); // --------- VIEW ------------- Ext.define('Iks.view.Themengebiet', { extend: 'Ext.grid.Panel', alias: 'widget.themengebiet', id: 'themengebietGrid', store: 'Themengebiet', viewConfig: { emptyText: 'Keine Datensätze gefunden' }, columns: [ { header: 'Id', dataIndex: 'id', width: 50 }, { header: 'Pos', dataIndex: 'pos', width: 30, editor: { xtype: 'textfield', allowBlank: false} }, { header: 'Themengebiet', dataIndex: 'themengebietname', width: 300, editor: { xtype: 'textfield' } }, { header: 'ConvertedField', dataIndex: 'posAndThemengebietname'} ], tbar: [ { xtype: 'button', text: 'Save' }, { xtype: 'button', text: 'Abort' }, { xtype: 'tbseparator' }, { xtype: 'button', text: 'Add' }, { xtype: 'button', text: 'Delete' } ], selType: 'rowmodel', plugins: [ Ext.create('Ext.grid.plugin.RowEditing', { clicksToEdit: 2, clicksToMoveEditor: 1, errorSummary: false, pluginId: 'rowEditingThemengebiet' }) ], initComponent: function () { this.callParent(arguments); } }); // --------- CONTROLLER ------------- Ext.define('Iks.controller.Themengebiet', { extend: 'Ext.app.Controller', models: ['Themengebiet'], stores: ['Themengebiet'], views: ['Themengebiet'], refs: [ { ref: 'themengebietGrid', selector: '#themengebietGrid' } ], reloadStore: function () { this.getThemengebietStore().load(); }, init: function () { //Event Handlers this.control({ '#themengebietGrid > toolbar > button[text="Save"]': { click: function () { this.getThemengebietStore().sync(); } }, '#themengebietGrid > toolbar > button[text="Abort"]': { click: function () { this.getThemengebietGrid().getPlugin('rowEditingThemengebiet').cancelEdit(); this.getThemengebietStore().rejectChanges(); } }, '#themengebietGrid > toolbar > button[text="Add"]': { click: function () { this.getThemengebietGrid().getPlugin('rowEditingThemengebiet').cancelEdit(); var record = Ext.create('Iks.model.Themengebiet'); this.getThemengebietStore().insert(0, record); this.getThemengebietGrid().getPlugin('rowEditingThemengebiet').startEdit(0, 0); } }, '#themengebietGrid > toolbar > button[text="Delete"]': { click: function () { this.getThemengebietGrid().getPlugin('rowEditingThemengebiet').cancelEdit(); var sm = this.getThemengebietGrid().getSelectionModel(); this.getThemengebietGrid().store.remove(sm.getSelection()); } } }); } }); // --------- APPLICATION ------------- Ext.application({ name: 'Iks', autoCreateViewport: false, controllers: ['Themengebiet'], launch: function () { Ext.create('Iks.view.Themengebiet', { renderTo: 'body'}); } });
HTML:
Code:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <!-- Test / Development --> <title>Test</title> <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" /> <link rel="stylesheet" type="text/css" href="ext-4.1.0/resources/css/ext-all.css" /> <script type="text/javascript" charset="utf-8" src="ext-4.1.0/ext-all-debug.js"></script> <script type="text/javascript" src="app.js"></script> </head> <body id='body'> </body> </html>
HELPFUL INFORMATION
Debugging already done:- When setting a breakpoint with Ext 4.0.7 on the model fields convert function, it stops after syncing store for converting data changed. With Ext 4.1.0 at same breakpoint code isn't stopped.
Operating System:- Win Server 2008R2
-
25 May 2012 1:17 PM #2Sencha - Senior Forum Manager
- Join Date
- Mar 2007
- Location
- St. Louis, MO
- Posts
- 33,714
- Vote Rating
- 436
To have the convert method execute you must always set that field to something even if it is an empty string.
Mitchell Simoens @SenchaMitch
Sencha Inc, Senior Forum Manager
________________
http://www.JSONPLint.com - Source to lint your JSONP!
Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
https://github.com/mitchellsimoens
Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/
Need more help with your app? Hire Sencha Services services@sencha.com
Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is almost in print!
When posting code, please use BBCode's CODE tags.
-
30 May 2012 11:12 PM #3
Some more questions
Some more questions
Mitchell,
shouldn't the convert function be called every time a record has changed or has been added?
Can you explain a bit more in detail what you meant?
-
31 May 2012 2:13 AM #4Sencha - Senior Forum Manager
- Join Date
- Mar 2007
- Location
- St. Louis, MO
- Posts
- 33,714
- Vote Rating
- 436
There would be performance suffering if that were true. It will only execute if you tell it to execute.
Will not fire the convert method on a fullName field to combine the firstName and lastName. In order to get the convert method to fire on the fullName field you would have to do:Code:rec.set({ firstName : 'Mitchell', lastName : 'Simoens' });
Notice since fullName uses the firstName and lastName in the convert method, you need to set the data for it after the other fields.Code:rec.set({ firstName : 'Mitchell', lastName : 'Simoens', fullName : '' });Mitchell Simoens @SenchaMitch
Sencha Inc, Senior Forum Manager
________________
http://www.JSONPLint.com - Source to lint your JSONP!
Check out my GitHub, lots of nice things for Ext JS 4 and Sencha Touch 2
https://github.com/mitchellsimoens
Think my support is good? Get more personalized support via a support subscription. https://www.sencha.com/store/
Need more help with your app? Hire Sencha Services services@sencha.com
Want to learn Sencha Touch 2? Check out Sencha Touch in Action that is almost in print!
When posting code, please use BBCode's CODE tags.
-
31 May 2012 3:26 AM #5
Mitchell, thanks for explanation.
In this case this is a new behavior in Ext 4.1 because in 4.0.7 this wasn't necessary.
In my case I use the Grid RowEditor. So I have to manually set the value to the field what isn't comfortable.
At the moment I am doing this before syncing:
Isn't there a possibility to tell the model or store to refresh all fields with convert function when syncing data?Code:this.getThemengebietStore().each(function (rec) { rec.set({ posAndThemengebietname: '' });
Thanks for helping
-
24 Aug 2012 10:52 AM #6Ext JS Premium Member
- Join Date
- Sep 2007
- Location
- Foothill-De Anza College District
- Posts
- 45
- Vote Rating
- 1
Hold on a Second!
Hold on a Second!
I am glad I found this thread because I am having a very similar problem as the OP.
Here is my converter:
Here is my field definition:Code:ActiveDivision.ux.converters.multiSessionValue = function(value, record) { // Examine the record, and only return values for "01" category sessions with the primary instructor console.log('multiSessionValue converted fired!'); if(record.get('meetno') == '01' && record.get('primary_instr') == 'Y') { return value; } return null; };
That converter function does not execute, and I know there is a value there because the GridView is rendering the value when all is said and done.Code:// ... {name: 'wsch_census', convert: ActiveDivision.ux.converters.multiSessionValue}, // ...
Mitchell your explanation makes sense, but I am still not getting the intended behavior. For my application I am loading records into the JsonStore using the load(...) method. When that load method runs, based on the defined convert function, it should be firing - right?
Please clarify.
Thank you!
-Matt
-
9 Sep 2012 2:35 PM #7
I'm having the same problem with the convert functions in my model. I load it from an XML file with an AJAX proxy. The convert functions gets executed and manipulates my XML into the right format. However when I later use MyRecord.set('status', 'An updated status') to update my record, the convert function is invoked again since 4.1.? and fails because now I'm not read from a XML but set the correct value directly!
This is very strange and I don't get why the convert function has to be called now every time!? Could you please indicate if this behaviour will change or will be left as it works now?
Looks like we can't reproduce the issue or there's a problem in the test case provided.


Reply With Quote