Using the ExtJS Row Editor

The RowEditor plugin was recently added to the ExtJS examples page. It works a lot like a normal Grid Editor, except you can edit several fields on a given row at once before saving.

This neatly solves the problem of adding a new row to an editor grid, entering data into the first field and finding it save itself straight away, which is rarely desired. In this fashion we can provide full CRUD for simple models in a single page.

Installation

You’ll need to get a copy of the javascript, css and images from the server. This is a bit of a pain. If you still have the ExtJS SDK around you can find these in the examples folder, if not you can get each file as follows:

Grab the plugin JS file below and put it where you usually put your .js files:
http://www.extjs.com/deploy/dev/examples/ux/RowEditor.js

This needs to go with your other stylesheets, usually in a directory called ‘css’:
http://www.extjs.com/deploy/dev/examples/ux/css/RowEditor.css

Download these two images and put them into your existing ‘images’ folder (the same place the other ExtJS images live):
http://www.extjs.com/deploy/dev/examples/ux/images/row-editor-bg.gif
http://www.extjs.com/deploy/dev/examples/ux/images/row-editor-btns.gif

Include the .js and .css files on your page and you should be ready to go.

Usage

RowEditor is a normal grid plugin, so you’ll need to instantiate it and add to your grid’s ‘plugins’ property. You also need to define what type of Editor is available (if any) on each column:

var editor = new Ext.ux.grid.RowEditor();

var grid = new Ext.grid.GridPanel({
  plugins: [editor],
  columns: [
    {
      header   : 'User Name',
      dataIndex: 'name',
      editor   : new Ext.form.TextField()
    },
    {
      header   : 'Email',
      dataIndex: 'email',
      editor   : new Ext.form.TextField()
    }
  ]
  ... the rest of your grid config here
});

RowEditor defines a few events, the most useful one being ‘afteredit’. Its signature looks like this:

/**
 * @event afteredit
 * Fired after a row is edited and passes validation.  This event is fired
 * after the store's update event is fired with this edit.
 * @param {Ext.ux.grid.RowEditor} roweditor This object
 * @param {Object} changes Object with changes made to the record.
 * @param {Ext.data.Record} r The Record that was edited.
 * @param {Number} rowIndex The rowIndex of the row just edited
 */
'afteredit'

All you need to do is listen to that event on your RowEditor and save your model object appropriately. First though, we’ll define the Ext.data.Record that we’re using in this grid’s store:

var User = Ext.data.Record.create([
  {name: 'user_id', type: 'int'},
  {name: 'name',    type: 'string'},
  {name: 'email',   type: 'string'}
]);

And now the afteredit listener itself

editor.on({
  scope: this,
  afteredit: function(roweditor, changes, record, rowIndex) {
    //your save logic here - might look something like this:
    Ext.Ajax.request({
      url   : record.phantom ? '/users' : '/users/' + record.get('user_id'),
      method: record.phantom ? 'POST'   : 'PUT',
      params: changes,
      success: function() {
        //post-processing here - this might include reloading the grid if there are calculated fields
      }
    });
  }
});

The code above simply takes the changes object (which is just key: value object with all the changed fields) and issues a request to your server backend. ‘record.phantom’ returns true if this record does not yet exist on the server – we use this information above to specify whether we’re POSTing to /users or PUTing to /users/123, in line with normal RESTful practices.

Adding a new record

The example above allows for editing an existing record, but how do we add a new one? Like this:

var grid = new Ext.grid.GridPanel({
  //... the same config from above goes here,
  tbar: [
    {
      text   : "Add User",
      handler: function() {
        //make a new empty User and stop any current editing
        var newUser = new User({});
        rowEditor.stopEditing();
        
        //add our new record as the first row, select it
        grid.store.insert(0, newUser);
        grid.getView().refresh();
        grid.getSelectionModel().selectRow(0);
        
        //start editing our new User
        rowEditor.startEditing(0);
      }
    }
  ]
});

Pretty simple stuff – we’ve just added a toolbar with a button which, when clicked, creates a new User record, inserts it at the top of the grid and focusses the RowEditor on it.

Configuration Options

Although not documented, the plugin has a few configuration options:

var editor = new Ext.ux.grid.RowEditor({
  saveText  : "My Save Button Text",
  cancelText: "My Cancel Button Text",
  clicksToEdit: 1, //this changes from the default double-click activation to single click activation
  errorSummary: false //disables display of validation messages if the row is invalid
});

If you want to customise other elements of the RowEditor you probably can, but you’ll need to take a look at the source (it’s not scary).

Final Thought

RowEditor is a really nice component which can provide an intuitive interface and save you writing a lot of CRUD code. It is best employed on grids with only a few columns – for models with lots of data fields you’re better off with a full FormPanel.

I’d be pretty happy to see this included in the default ExtJS distribution, as I find myself returning to it frequently.

43 Responses to Using the ExtJS Row Editor

  1. Have you tried to disable all editors in a single row without affecting the whole column?

  2. Fadel says:

    hi

    i have a probleme with dates, my app send this format of date to the server ( Fri Nov 13 2009 00:00:00 GMT+0100 )

    there is a solution

    thanks

  3. kpmonroe says:

    Thanks for this in-depth tutorial.

    Just wanted to point out that as of version 3.0.1, RowEditor has added a cancel event that makes adding new records quite easier. The basic gist is that a user might elect to add a record then cancel before saving. By listening for the cancel event you can make sure that the new record is not retained in the store when the user has elected to cancel.

  4. ang89 says:

    Usefull plugin !

    However, the row editor defaults to submit the changes in “dataindex – value” pair. I think this plugin should have an option so that the user can submit as “fieldname – value” pair instead. I need this. Currently, I solve this by messing up with RowEditor.js source code.

  5. Sergiu says:

    Hi,
    There are some difference between 3.1.1 and 3.0.0, so be careful what version of Ext you have. Also I would like the RowEditor.js file for the 3.0.1 version, the on e with the cancel event.
    Thanks, Sergiu

  6. Exty says:

    What about editon last row, Update/Canel buttons are not visible there?

    Thanks for your tutorials!

  7. Pingback: ExJS入門27 もう一つのエディタブル・グリッド ux.RowEditorプラグイン | ExtJSで楽しくRIA業務アプリ開発

  8. firmansyah says:

    hi, i’m looking solution for my problems with this row editor.
    if the grid resize or move the columns, for the first time the row editor is fine,but in second time,if you do resize or move columns again,in next row editor will show not fine,it is untidy.
    Thanks.

  9. Ed Spencer says:

    @firmansyah we’re aware of several problems with the RowEditor currently – it’s high on the list of things to fix

  10. TB says:

    Repositioning or moving column headers in the grid screws up the editor row fields. Any ideas?

  11. Ed Spencer says:

    @TB there are several major known issues with RowEditor. It’s high on the list for a rewrite, probably coinciding with 4.0

  12. mayuri says:

    can anyone post the back end php for row editor. it will be usefull for many of us..

  13. Thanks man, I was making a silly mistake, I’ve found it with this tuto.

    bye

  14. hachie says:

    I’ve one problem with RowEditor.
    When I update or insert a row, if I visite all the fields with TAB key is all right, but when I arrive at finish of rows with TAB key and after with mouse I come back at start of row sometimes firebug give me a error “j is null” and I can’t navigate the fields with TAB key.
    What am I doing of wrong?
    Sorry for my english.

  15. Very useful plugin indeed !! Using it for my grid w some other custom functionalities.

  16. Toby says:

    how do i change line below if ‘update.php’ just in same directory as grideditor.js ?
    ——————————————————————————————————————–

    url : record.phantom ? ‘/users’ : ‘/users/’ + record.get(‘user_id’),
    method: record.phantom ? ‘POST’ : ‘PUT’,

    ——————————————————————————————————————–
    i trying “url : record.phantom ? ‘update.php’ : ‘update.php’ + record.get(‘user_id’)” but not working.

    update.php (OCI8) :

  17. Laurent Malvert says:

    There is a slight “bug” in the RowEditor, both in version 3.0.0 and version 3.2.1 from what I have tested. Basically a refresh of the grid view will eventually call the stopEditing() method, which in turn will call the afteredit() handler… where there’s a good chance at least some people will try to refresh their gridview, and not only reload its data.

    Ok maybe not “some people”, but me, as I have a table with heterogeneous cell-types and need to hot-swap the cell editors in the RowEditor depending on the row I edit. Which means I need to call refreshFields() on the editor, but also refresh() on the GridView. And then it’s unhappy (infinite recursive loop, indeed. Well, until the JS engine’s stack dies anyways). There’s an easy patch for it, by just adding an “if (!this.editing) { return ; } at the top of the stopEditing() method. Don’t know if that can help others, but that kept me busy for a little while today.

  18. Ed Spencer says:

    There are numerous problems with RowEditor in 3.x, most of them not surmountable in the current major release. We have an awesome new replacement coming in Ext JS 4.0 though.

  19. Laurent Malvert says:

    Looking forward to see it. Hope its general design is not too different though, both in terms of UI and API, as I wouldn’t want to spend too much time upgrading. But if that’s worth it, I’d be glad to and I’m sure it will be worth the wait. Can we see a preview?

  20. Ed Spencer says:

    General design and API very much the same, definitely worth the upgrade. No preview yet 🙂

  21. Jigar Chaudhary says:

    Hi,

    Thanks in advance for help me.

    i have problem with add new record then Cancel that record but that not remove that newly added record please help me.

  22. Pratik Khanna says:

    I want to edit a particular field using the row editor but on a right click menu when I choose ‘edit’ out of the other menu options, the record should become editable. Is it possible with Row Editor?

  23. Alex says:

    I am trying to use the roweditor plugin with two independent grids within the same window:

    var editor = new Ext.ux.grid.RowEditor();

    var firstGrid = new Ext.grid.EditorGridPanel({ id : ‘firstgrid’,
    store: firstStore,
    plugins: [editor],
    sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),
    columns: firstModel,

    });

    var secondGrid = new Ext.grid.EditorGridPanel({ id : ‘secondgrid’,
    store: secondStore,
    plugins: [editor],
    sm: new Ext.grid.RowSelectionModel({ singleSelect: true }),
    columns: secondModel,

    });

    The problem in secondGrid this works fine. However, clicking a row in firstGrid brings up the editor in secondGris.
    My gut feeling says I am doing something fundamentally wrong here. Why isn’t a new instance of the row editor created for each grid?

  24. Ed Spencer says:

    @Alex you need to create a second RowEditor instance. There are several ways to do this, the easiest would be to simply duplicate your first line (e.g. var editor2 = new Ext.ux.grid.RowEditor();)

  25. Prashant says:

    is RowEditor plugin compatible with Extjs 2.1???

  26. Varun Achar says:

    Hi Ed,

    Suppose I add a new record to the grid, start editing the record (haven’t clicked on save yet), but now I want to discard the record. Cancel currently only stops editing of that record and brings it back to its original state, so right now i have a empty row at the top of my grid.

    What do I do to remove the row when i click the cancel button if the record corresponding to that row is a phantom record?

  27. Archana P says:

    Looking for an answer for the same question as posted by Varun Achar above:

    ‘What do I do to remove the row when i click the cancel button if the record corresponding to that row is a phantom record?’

    Any assistance would be appreciated.

  28. Pingback: extjstutorial.org

  29. Hailey says:

    Hello,

    I think I have similar problems that hachie and firmansyah had: the tab key doesn’t work on row editor (gives ed (activeEditor I think) is null) and the row editor comes up in a weird shape after resize. You said that these features will be improved on Ext JS 4, but are there any ways to override the row editor from Ext JS 3.3.1 to fix these two problems?

    Thanks!

  30. Farish says:

    Hi Ed,

    I also have the same problem as the others. There is no cancel event in Ext JS 4.0 (at least not a documented one). When a user adds a new row and then clicks Cancel or presses escape, there is an empty row in the grid which I would like to remove on the cancel event. Could you please suggest a way to do this?

    Regards,
    Farish

  31. Farish says:

    also, the savetext and canceltext isn’t working for me. I am using the following code in (Ext JS 4):

    var rowEditing = Ext.create(‘Ext.grid.plugin.RowEditing’, {
    id:’rowEditing’,
    clicksToEdit: 2,
    saveText: ‘Add’
    });

    but I still see “Update” on the button.

  32. Farish says:

    @All above who want to remove newly added row or perform some other action when the Cancel button is clicked or Escape key is pressed in rowediting (in Ext JS 4):

    // Override the cancelEdit function of RowEditing plugin
    Ext.override(Ext.grid.plugin.RowEditing, {
    cancelEdit: function() {
    var me = this;

    if (me.editing) {
    me.getEditor().cancelEdit();
    me.callParent(arguments);

    this.fireEvent(‘canceledit’, this.context);
    }
    }
    });

    // Create plugin to be used in grid:
    var rowEditing = Ext.create(‘Ext.grid.plugin.RowEditing’, {
    id:’rowEditing’,
    clicksToEdit: 2
    });

    // Use canceledit event to remove the added record from the store (or use what you want in this function!)
    rowEditing.on(‘canceledit’, function(context) {
    context.record.store.remove(context.record);
    });

    Hope this helps others.

    Regards,
    Farish

  33. Ed Spencer says:

    @Farish and others: thanks for the suggestion on the canceledit event – I’ve added this to the row editor now and it will show up in the next patch release (4.0.5). Expect this in the next 7-10 days

  34. Farish says:

    @Ed: thanks for adding it. but i discovered an error in this approach while testing it today. If you add and then press cancel, the row disappears (like we want to). but now if you click a row for editing and then press Cancel, that existing row is also deleted since it calls the cancelEdit function! Please check this.

  35. Flanders says:

    Uhm, Since I wrote the code provided by Farashi I was wondering how I could reproduce the error he points out since that code is already in production and I cannot see how to reproduce the error.

  36. Nickname says:

    @Farish
    For me works follow small enhance :

    // Override the cancelEdit function of RowEditing plugin
    Ext.override(Ext.grid.plugin.RowEditing, {
    cancelEdit: function() {
    var me = this;
    if (me.editing) {
    me.getEditor().cancelEdit();
    me.callParent(arguments);
    this.fireEvent(‘canceledit’, me.context);
    }
    }
    });

    var rowEditing = Ext.create(‘Ext.grid.plugin.RowEditing’, {
    clicksToMoveEditor: 2
    ,autoCancel: false
    ,listeners: {
    canceledit: function(context){
    if(!context.record.data.id && context.record.store)
    context.record.store.remove(context.record);
    else
    context.record.reject(true);
    }
    }
    });

  37. Farish says:

    For changing button text from “Update” and “Cancel” to your own desired values, the following may be used in ExtJS 4:

    Ext.grid.RowEditor.prototype.cancelBtnText = “My cancel button text”;
    Ext.grid.RowEditor.prototype.saveBtnText = “My update button text”;

    this has to be done before you create your rowediting plugin. however, I am still looking for a way to be able to change the text after creation of the plugin. e.g. I would like to change the value to “Add” when a new record is entered by the user and “Update” when an existing one if clicked for editing.

  38. fuser says:

    hello,

    Does this code works with extjs 2.2.1?

    thank you

  39. hemsingh1986 says:

    how can i make a dateField in column by extending the roweditor. in Extjs 4.2.2

  40. hemsingh1986 says:

    How can we override geteditor.
    if i need a date field in my column cell?

  41. Pingback: Extjs Html Editor Remove Toolbar - Remove Spyware, Malware and Viruses

  42. You actually make it appear really easy together with your presentation but I to find this topic to be actually something which I believe I would never understand.
    It seems too complicated and very large for me.
    I am having a look ahead on your subsequent post, I will try to get the hold of
    it!

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 )

Connecting to %s

%d bloggers like this: