4
votes

i want to intercept field get/set on a model so that i can transform the values before they get displayed as well as before they get stored in the model. in this case, i want to store uriencoded data in the model, but display decoded values.

when i directly override the get/set methods i see that they are being used by the proxy to put raw data into the model. i dont want to override that process and i am not even sure how to tell whether it is the proxy loading a model or the ui.

what is the best method for this? convert, btw, appears to be a poor choice. it is not 2-way and live.

1
convert() is two-way method. I use it for example to convert back and forth decimal color codes to hex. - sha
Just so I understand.. (1) when retrieving data, you are encoding data on the server before the ajax get and then decoding it before displaying data to end-user? (2) when passing data in the URL, you encode, then decode in Ext JS when you use the data? (3) When saving data, you have Ext JS encode, then pass to the server and decode before storing? - MacGyver
how is convert a 2-way function? it looks to me like it only gets called when something is reading a value from a record ie. myRec.get('field1'). is there a convert equivalent getting called during a write operation ie. myRec.set('field1', 'new value')? - Paul

1 Answers

4
votes

Note: I have not tested this code, so use the concepts and comment later if you have questions.

When you define your Ext.data.Model class for your data entities (use Ext.data.Record for Ext JS 3), add a convert function as part of your Ext.data.Field property instance. This can be done for all fields if you want, but probably not recommended.

I'm new to this framework, so one thing I do not know how to do is use the "this.self" notation in the convert function in case you are extending another class in your Model class. For example, if you do not have a default value defined in the Employee class and it inherits from another class (like Employee for example), but the Employee constructor sets that property, it'll take the value defined in the super class (base class or parent class) constructor when you encode the data. Right now, it just gets the EmployeeDeveloper.dataValue property.

Ext.define('EmployeeDeveloper', {
  extend: 'Ext.data.Model',
  fields: [
    { name: 'name', type: 'string', defaultValue: 'Paul' },
    { name: 'profession', type: 'string', defaultValue: 'Ext JS developer' },
    { name: 'salary', type: 'float', defaultValue: '95000' },
    { name: 'dataValue', type: 'string',
      convert: function(value, record) {
        // feel free to use value and record parameters in this function
        return encodeData(record.get('dataValue'));  // you may have to use the "value" parameter instead of record.get('dataValue') if referencing the field in it's own convert function (haven't tested)
      }
    }
  ]
});

var empDev = Ext.create(
  'EmployeeDeveloper', 
  {
    name: 'MacGyver',
    dataValue: 'ABC'
  }, 
  'MacGyver', 
  123
);

var encodedDataValue = empDev.get('dataValue');

Caution about convert: If you are referencing a field that is defined below the convert function signature, the code will not know about it and won't be able to retrieve the value.

OR IF YOU HAVE A CUSTOM CLASS BUT NOT USING THE MODEL CLASS...

Tonight I also read about something else that's kind of neat in Ext JS. They added auto getters and setters in Ext JS 4. The new version of the framework automatically prefixes your property with "get", "set", "reset", or "apply" and capitalizes the first letter of the property inside of the "config" property of your defined class.

In regular JavaScript, they don't have real classes, but Sencha has made it possible to define a class (with the "define" function) and the ability to instantiate an object instance of your user defined class.

For example, suppose you have the following class defined:

Ext.define('Paul.MyClass'), {
  extend: 'Ext.Window',
  config: {
    name: 'Paul'
  }
});

If you create an instance of your object like so, you automatically have access to four functions.

var win = Ext.create('Paul.MyClass');  // create instance of MyClass object
var myName = win.getName();  // get name
win.setName('MacGyver');  // set name
win.resetName(); // this resets the value back to the default value ('Paul')
win.applyName();  // this calls custom code 
win.show();

I'd suggest overriding the apply* method with the logic you are suggesting. Then calling win.get*(); afterward to get the new value. It might be wise to have an extra encoded field for each field you plan on encoding so you don't have to manipulate your properties every time you access (get or set) your data in your proxies and/or stores.

Ext.define('Paul.MyClass'), {
  extend: 'Ext.Window',
  config: {
    name: 'Paul',
    dataValue: 'non encoded value of your data'
  }
  applyName: function(title) {
    this.name = this.name + ' ' + title;  // custom logic goes here
  }
  applyDataValue: function(encodeKey) {
    // get the encoded data value
    this.self.dataValue = 'encoded data value';  // custom logic goes here
  }
});