Skip to content

March 22, 2011

22

Changing column’s editor dynamically in ExtJS RowEditor

by Joe Kuan

This article is to demonstrate how to change the editor in a column dynamically with RowEditor. Suppose you have a ExtJS Grid with several columns, one of the columns indicates the value type of another column. In another word, the type column’s editor is a ComboBox object for selecting different types whereas the value column’s editor varies associating with that type. This is trivial to do in a simple GridPanel object. However, for more sophisticated RowEditor is slightly tricky.

RowEditor

The basic idea behind RowEditor is a Panel object that lays on top of the editing row. Then inserts each column’s editor into it’s items field with value and displays them respectively. Simply changing the underlying GridPanel’s column editor does not reflect the change to the RowEditor. You will also need to manually insert the new editor into the RowEditor.

Here is part of my code for the ColumnModel of two columns. The first column (type column) editor is a ComboBox which is fixed.

}, {
   dataIndex: 'column_type',
   sortable: true,
   header: 'Column Type',
   width: 160,
   editor: {
      xtype: 'combo',
      mode: 'local',
      store: columnTypeStore,
      triggerAction: 'all',
      autoSelect: true,
      editable: false,
      displayField: 'type_name',
      valueField: 'id',
      listeners: { ...

The second column (value column) editor is a Textfield to start with.

}, {
  dateIndex: 'compare_value',
   id: 'cmp_value',
   sortable: true,
   width: 200,
   header: 'Value',
   editor: {
      xtype: 'textfield',
      allowBlank: false
   }
}, {

The next step is to add an event handler for the first column ComboBox when a value is selected. Creates a new editor and set the target column’s editor to the new editor. Then links the RowEditor content with the new editor manually.

          listeners: {
            select: function(combo, record, index) {
                var cm = Ext.getCmp('color_editor').getColumnModel();
                var valCol = cm.getColumnAt(3);
                var change = false;

                // This part is to compare the select type against the current
                // editor's xtype. If not as expected, set a new editor to the
                // value column
                if (record.data.type == 'int' &&
                    valCol.getEditor().getXType() != 'numberfield' ) {
                  // Create and replace with a new editor in the target column
                  valCol.setEditor({
                     xtype: 'numberfield',
                     allowBlank: false,
                     allowNegative: false,
                     allowDecimals: false,
                  });
                  change = true;
                } else if (record.data.type == 'ip' &&
                    valCol.getEditor().getXType() != 'textfield') {
                  // Create and replace with a new editor in the target column
                  valCol.setEditor({
                     xtype: 'textfield',
                     allowBlank: false,
                     allowNegative: false,
                     vtype: 'IPAddress',
                  });
                  change = true;
                } else if (record.data.type == 'ip group' &&
                    valCol.getEditor().getXType() != 'combo') {
                  // Create and replace with a new editor in the target column
                  valCol.setEditor({
                     xtype: 'combo',
                     allowBlank: false,
                     editable: false,
                     autoSelect: true,
                     triggerAction: 'all',
                     store: ipGrpStore,
                     displayField: 'name',
                     valueField: 'id',
                  });
                  change = true;
                }

                // If a new editor is setup, then update to the RowEditor
                if (change) {
                  var new_editor = valCol.getEditor();

                  // This margin code is taken from RowEditor code
                  var pm = pm = Ext.layout.ContainerLayout.prototype.parseMargins;
                  if (Ext.isIE) {
                     new_editor.margins = pm('0 0 2 0');
                  }
                  else {
                     new_editor.margins = pm('0 1 2 0');
                  }
                  new_editor.setWidth(cm.getColumnWidth(3));

                  // Insert and adjust the new editor
                  editor.insert(3, new_editor);
                  editor.verifyLayout(true);
                }
              }  // select
            }  // listener

A few notes about the above listener code, the variable editor is an object of RowEditor. The margins code is taken from the RowEditor.initFields method. As I knew my value column is not at either end of the editing row, so I only copy the code dealing with the margins for the in-between columns.

In my own example, I need to change the value column editor between TextField, NumberField and ComboBox. Here are couple screenshots.

[Update] For ExtJs 4 example, see this

Advertisements
22 Comments Post a comment
  1. Jun 22 2011

    My god you’re a life saver.. I did everything you did expect for the the verifyLayout() .. i spent nearly 4 hours trying to figure it out and would’ve wasted a lot more time if I hadn’t stumbled upon this..

    Thank you!

    Reply
  2. Lucas Fabiano
    Aug 10 2011

    Very nice code.
    I’m trying to figure out who is editor who does verifyLayout.
    I’m working with Extjs 4 and I can’t figure out.
    Can you help me?

    Reply
  3. Lucas Fabiano
    Aug 11 2011

    **Solution for Ext4:**

    I was looking for a solution for this and this guy said the property grid has this behavior.
    I have adapted it to work in a clean way for me
    on initComponent I declared:

    this.editors = {
    ‘date’ : Ext.create(‘Ext.grid.CellEditor’, { field: Ext.create(‘Ext.form.field.Date’, {selectOnFocus: true})}),
    ‘string’ : Ext.create(‘Ext.grid.CellEditor’, { field: Ext.create(‘Ext.form.field.Text’, {selectOnFocus: true})}),
    ‘number’ : Ext.create(‘Ext.grid.CellEditor’, { field: Ext.create(‘Ext.form.field.Number’, {selectOnFocus: true})}),
    ‘int’ : Ext.create(‘Ext.grid.CellEditor’, { field: Ext.create(‘Ext.form.field.Number’, {selectOnFocus: true})}),
    ‘boolean’ : Ext.create(‘Ext.grid.CellEditor’, { field: Ext.create(‘Ext.form.field.ComboBox’, {
    editable: false,
    store: [[ true, ‘Sim’ ], [false, ‘Não’ ]]
    })})
    };

    I used these functions to help me (copied):

    this.renderCell = function(val, meta, rec) {
    var result = val;
    if (Ext.isDate(val)) {
    result = me.renderDate(val);
    } else if (Ext.isBoolean(val)) {
    result = me.renderBool(val);
    }
    return Ext.util.Format.htmlEncode(result);
    };

    this.getCellEditor = function(record, column) {
    return this.editors[record.get(‘type’)];
    };

    And finally, associate these functions to the column:

    {text: “Valor”, name : ‘colunaValor’, width: 75, sortable: true, dataIndex: ‘valor’, width:200,
    renderer: Ext.Function.bind(this.renderCell, this),
    getEditor: Ext.Function.bind(this.getCellEditor, this)
    }

    Reply
    • mohan
      Sep 2 2011

      Hi Lucas, can you please send me the code which you have implemented using extjs4 to mohankjn@yahoo.com

      Reply
    • mprogr
      Sep 13 2011

      hi. please send me this solution to munkherdenet@yahoo.com

      Reply
    • Sep 20 2011

      Thanks for sharing Lucas,I am suffering from combo box field in row-editable gid in extjs 4.0 , if you have sample code,and required renderer function for combobox field,
      could you please send me the code to bzjrpkyz@hotmail.com .
      thanks again.

      Reply
    • nansen serguiev
      Oct 19 2011

      can you please send me this solution
      nansenserguiev@yahoo.com
      thanks

      Reply
    • Apr 11 2012

      Hi i am trying this code in extjs4. I am getting record is null in following function.
      this.getCellEditor = function(record, column) {
      return this.editors[record.get(‘type’)];
      };

      Can you please share the working code for this.

      Thanks in advance

      Reply
      • Olivier
        Jun 3 2013

        Hi

        I have the same issue as you. Did you manage to solve ?

    • suamikim
      May 30 2012

      Hi there,

      can anyone please send me a working example of this for ExtJS 4 too?

      suamikim[at]gmx.net

      Thanks

      Reply
  4. arunkumar
    Nov 24 2011

    hi. please send me this solution to arunkumar.ps82@gmail.com

    Reply
  5. Ballu
    Nov 29 2011

    Hi Lucas
    Great code, I tried to implement this using 4.0.6 and am stuck with few JS errors that I cannot solve. can you please email your code to balaram.geo@yahoo.com
    Thanks

    Reply
  6. SunShine
    Dec 28 2011

    Hi Lucas
    Great Code, i to am struck in JS errors can you send me your code sunwpk@yahoo.com
    Thanks

    Reply
  7. Vin
    Feb 21 2012

    Hi Lucas,

    Superb code. Can you please provide the complete code.

    svinaysrinivas@gmail.com

    Thanks

    Reply
  8. vinay
    Feb 21 2012

    supercode lucas can u please mail your code to svinaysrinivas@gmail.com

    Thx
    Vin

    Reply
  9. Steve
    Mar 12 2012

    Using ExtJS 3.3.1 I’m getting multiple JS errors when trying to change from a datatype other than the default to the default. In other words, if my default is textfield and I choose combo it works fine. But if I then change my mind and choose textfield I get the following 2 errors:
    1. On editor.verifyLayout(true): ‘getPositionEl().dom.parentNode’ is null or not an object.
    2. On closing bracket of listener: ‘this.dom.value’ is null or not an object

    Reply
    • Steve
      Mar 12 2012

      Solution: I was trying to create variables for my edit objects (textfields and comboboxes) and then referencing them in the column.setEditor methods (e.g. valCol.setEditor(myTxtFld);). This does not work.

      However you can point the setEditor method to a function that returns the edit object (e.g. valCol.setEditor(getMyTxtFld());), eliminating the need to define the same config for an object in multiple places.

      Reply
  10. Steve
    Mar 19 2012

    I’m using virtually identical code to that above with ExtJS 3.3.1. I open the window and load the grid with data from the database. I then need to edit a row that requires the numberfield for the value. The issue is that since the default value editor is a textfield, the numberfield is displayed in the first column behind the textfield used to edit that column. If I then cancel my edit and edit another row with either the textfield or combobox as the editor then return to edit the numberfield row it is displayed correctly in the third column.

    I compared the code above with that in the RowEditor and found that you did not include “ed.column = i” near the end. If I use only that line and remove the “ed.insert(i, new_ed)” then the numberfield is displayed properly however I get other js errors when I try to add a new row. If I include both lines of code then the numberfield is still displayed behind the first column but the js errors are resolved.

    Suggestions on how to ensure that the non-default editor is displayed correctly in the 3rd column when it is the first row edited after a fresh page load?

    Reply
  11. Anand
    Jun 25 2012

    Modified code to try to get it to work with 4.0.7, however it seems to throw an error ‘Uncaught TypeError: Object [object Object] has no method ‘getEditor” in the valCol.setEditor() call. Its being thrown from the grid.plugin.RowEditor I. anyone have a working 4.0 example?

    Reply
  12. Kevin Guto
    Apr 5 2014

    Gracias !

    Reply

Trackbacks & Pingbacks

  1. extjs4 grid – changing column editor per row basis

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Note: HTML is allowed. Your email address will never be published.

Subscribe to comments

%d bloggers like this: