DataGrid Double-Click To Edit

Several people have asked about changing the default editing behavior of a DataGrid so that starting an edit session requires a double-click instead of the default single-click.
Here’s my approach:
Download Source
Run Demo

43 Responses to DataGrid Double-Click To Edit

  1. srouse says:

    Seems to introduce a new bug…if you scroll with something being edited, the next attempts to edit a field selects the wrong field. (using 9,0,45,0 on Win)
    —————————
    Alex responds:
    Thanks for catching that. I uploaded a fix for that.
    I should also mention that this solution presumes that all renderers implement IDropInListItemRenderer.

  2. Boubalou says:

    Hey Alex,
    I don’t know why under my IE7 in Vista you last couple of blog posts with demos cannot be loaded. The SWF generate an invalid char javascript error of some sort.
    I have to load it within Firefox to get it to work.
    -Boub

  3. Jana says:

    I’m running Windows XP and use IE 7.0 but cannot view the swf files either. I too have to use Firefox.
    ———————
    Alex responds:
    Hmm, maybe I’ll have to upload html wrappers as well.

  4. malone says:

    I’ve implemented the same functionality, but in a different way. My class just simulates a single-click when a double-click occurs. That way it should still work even if the code for DataGrid is changed in the future.

    public class DoubleClickDataGrid extends DataGrid {
    public function DoubleClickDataGrid() {
    super();
    doubleClickEnabled = true;
    }
    override protected function mouseDoubleClickHandler(event:MouseEvent):void {
    super.mouseDoubleClickHandler(event);
    // simulate a click (just calling the mouseUpHandler wont work)
    super.mouseDownHandler(event);
    super.mouseUpHandler(event);
    }
    override protected function mouseUpHandler(event:MouseEvent):void {
    // prevent edits on normal mouse-up
    var saved:Boolean = editable;
    editable = false;
    super.mouseUpHandler(event);
    editable = saved;
    }
    }

  5. abZ says:

    Hey,
    Thanks so much for this, helped a lot!!!
    p.s I used this on a Flex desktop app hooked up to a datagrid that is feed via xml
    thanks,
    abZ
    (i think i may have this comment incorrectly on another post please disregard the other)

  6. Yasir says:

    that is nice thing. How can I do it for tree control.
    It does not have dataColumn.
    Regards
    Yasir
    ———————-
    Alex responds:
    You should be able to replace that event with similar code from List.as like this:
    var listEvent:ListEvent =
    new ListEvent(ListEvent.ITEM_EDIT_BEGINNING, false, true);
    // ITEM_EDIT events are cancelable
    listEvent.rowIndex = rowIndex;
    listEvent.columnIndex = 0;
    dispatchEvent(listEvent);

  7. Jeff Peck says:

    I am trying to make a tree that upon a particular drag and drop will immediately make the item that was just dropped to be an editor.
    The idea is to have a tree where a “New Item” can be dragged into a particular place in the tree and once it is dropped, the user has the ability to name it. If the user decides not to name it, it should go away.
    I have been trying for some time to make this to no avail. This post is the first thing that I have found that has been helpful. If anyone here has any additional info that might be useful for what I am doing I would appreciate it.
    Thanks.
    ————————–
    Alex responds:
    I assume you saw this post as well? http://blogs.adobe.com/aharui/2008/03/custom_arraycollections_adding.html

  8. Mike Slinn says:

    Any suggestions on how to double-click on an unused list entry in order to insert a new item?
    ———————-
    Alex responds:
    Start here: http://blogs.adobe.com/aharui/2008/03/custom_arraycollections_adding.html

  9. Ahmed ElDawy says:

    I found some issue with this. I transofrmed it to work with List. Elements in the list can be deleted with key. After deletion, it starts editing at the newly selected item.
    Do you have a solution for this?
    —————-
    Alex responds:
    You didn’t say where you want it to go. I’d probably put in some mode where you’re in “newEntry” mode or not and when someone clicks delete switch out of newEntry mode and run the List normally.

  10. Marcus Fritze says:

    I use your DoubleClickDataGrid with an ItemEditor. The ItemEditor consists of 1 TextField and 2 Buttons (Cancel and Submit). And the DoubleClickDataGrid is in a Repeater.
    Now my question: how can I control (cancel or submit) the ItemEditor with this 2 Buttons correctly?
    At present, I use KeyboardEvents. That means when I click the Cancel-Button, I “dispach” the KeyCode 27 to the TextInput in the ItemEditor (and the KeyCode 13 when Submit is clicked).
    Is this good style? Because now I have some problems with your DoubleClickDataGrid – Component.
    When I click the Cancel-Button in the current ItemEditor the edit will be canceled and the old value of this cell is in this cell (like you press the Esc Button on you Keyboard).
    This works fine.
    When I click my submit button, the old value will be replaced with the new one (like you press the ENTER Button). But now when I click (one time – not doubleclick) in a row of another or the same DoubleClickDataGrid in the Repeater the ItemEditor starts!?
    This only happens when I use my submit-Button.
    When I use my cancel-Button, ESC, ENTER or focusout with the mouse, this did not happened.
    Any idea?
    ———–
    Alex responds:
    I would try dispatching an itemEditEnd event with different DataGridEventReasons for submit and cancel

  11. pinto says:

    This is really a good and very useful to me.
    But i need to double click edit the tree control, even i have followed the same way which is there in List.as
    But it is not working as expected.
    Could you please help me out in getting the tree editable on double click
    ———————-
    Alex responds:
    I don’t have time right now. I’d ask for help on FlexCoders.

  12. Bill Shirley says:

    Another option is to prevent the List (et al) from editing when you don’t want it to. Subclassing is not required for this option. Use the itemEditBeginning and prevent the default action (editing the item).
    I chose to use the rowIndex and require a second click. You can change the rowIndex without “clicking”, so i fixed that with the itemClose/itemOpen events.
    Sometimes it will edit on a single click if you’ve been collapsing or opening the branches. That could be solved by listening to itemOpen/itemClose events.

    itemEditBeginning=”confirmEdit(event)”
    itemOpen=”previousIndex=-1″
    itemClose=”previousIndex=-1″
    />
    private var previousIndex:int;
    private function confirmEdit(event:ListEvent):void {
    if (previousIndex != event.rowIndex) {
    previousIndex = event.rowIndex;
    event.preventDefault();
    }
    }

    keywords: Tree Flex edit on double click

  13. Kalle Blorin says:

    Thanks for that grid! My comment here is somewhat on the side of a doubleclick grid, but it is related enough that I post it here. I am using your grid, but I want to be able to use my keyboard for navigating it. I am trying to make an F2 KeyboardEvent fake a double click, so that I can edit a cell. My problem is that the ‘edit index’ seems to not move when I keyboard UP or DOWN through the list. Also, my F2-triggered doubleclick on the Datagrid event does not seem to actually do anything. Might you have time to give me a hint..?
    Thanks!
    —————————-
    Alex responds:
    On F2, set editedItemPosition.

  14. Carrie says:

    Thanks, this works great for editing on double click. However, I would also like to handle the single click event. Any tips since the single click fires before the double click?
    ———————————
    Alex responds:
    Not sure what you want to do, but you can always respond to MouseEvent.MOUSE_DOWN or CLICK

  15. mirv says:

    2 questions
    1-how can i do to set the entire row editable?
    2-how can i pass a parameter(parameterTest) in a row
    and get this parameter in ‘as’ class
    dgColumn = columns[dilr.listData.columnIndex];
    dgColumn.editable = false;
    to set whether is editable or not
    thank you
    ———————
    Alex responds:
    you can’t make the whole role editable at once although you could try floating a single column’s editor over the whole row.
    The .data property of the renderer is the entire data item and you can pull other properties off it.
    To deny editability of a particular cell, you call preventDefault on the ITEM_EDIT_BEGINNING event. Setting the flags will not work.

  16. Vajahat says:

    Thank You Adobe and Alex
    Great Blog by Alex, special thanks to Adobe Team
    Regards,
    Vajahat Ali
    Software Engineer
    Software Innovations
    Lahore,Pakistan

  17. YopSolo says:

    my way to do it :
    in the constructor : doubleClickEnabled = true;
    addEventListener(ListEvent.ITEM_DOUBLE_CLICK, onEdit, false, 0, true ); addEventListener(ListEvent.ITEM_FOCUS_OUT, onEditing, false, 0, true );
    then i clone and change the message send by the List/Datagrid
    private function onEdit( e:ListEvent ):void
    {
    this.editable = true;
    var clone:ListEvent = new ListEvent( ListEvent.ITEM_EDIT_BEGINNING,
    e.bubbles,
    e.cancelable,
    e.columnIndex,
    e.rowIndex,
    e.reason,
    e.itemRenderer);
    dispatchEvent( clone );
    }
    private function onFocusOut( e:ListEvent ):void
    {
    this.editable = false;
    }
    and it’s done 😀

  18. Zed-K says:

    Hi Alex.
    Thanks for the exemple, I was actually looking how to do that, and your post saved me a lot of time 😉
    I just have a little but yet annoying bug :
    – Click on an editable field of the datagrid
    – Give the focus to an other window (using alt+tab for instance)
    – Return to your browser/standalone player : the field enters in edition state :/
    It seems to happen when the “activate” event is dispatched, but I haven’t been able to find why :s
    ————————-
    Alex responds:
    That might be fixed when 3.4 comes out (due ‘soon’), but for now you should be getting an ITEM_EDIT_BEGINNING event that you can use to block the edit session.

  19. Stuar says:

    Hi Alex,
    the demo looks great, I do have a problem though….I am recently new to Flex and I am doing something wrong. I have a working program that has a HttpService tag and handler that populates a datagrid from mysql.
    I changed the mxml to read local:DoubleClickDataGrid as per your example and created a new ActionScript class file in my project with your class code in it.
    When I compile I get an error in the mxml at the line with a message that the prefix local is not bound.
    After some googling I am lost…any clues appreciated as to what I have done wrong much appreciated. Thanks for your time and sharing this with the community.
    Stu.
    ——————-
    Alex responds:
    You probably have to add xmlns:local=”*” or some path in your top tag next to the xmlns:mx attribute

  20. Bill says:

    Hi Alex, Great postings! I’ve tried to implement your example, but it doesn’t work as I have custom editors/renderers and I think that’s what is causing the problem. I’m already using a custom DG that allows me to keep focus in my editor as a couple of the column editors have multiple fields. Any thoughts?
    ———————
    Alex responds:
    Maybe instead of a custom DG, use the post about multi-field editors

  21. Stuart says:

    Hi Alex,
    I have got this working now but am relatively new to flex – after googling to confusion I hope you can point me in the right direction.
    When my table was a simple datagrid I had the following event defined:
    tagsGrid.addEventListener(DataGridEvent.ITEM_EDIT_END, updateTagItem);
    where tagsGrid is the name of the datagrid.
    now I have changed the datagrid to DoubleClickDataGrid the event listner fails with “cannot access property or method of null object reference”
    could you tell me how to refer to the custom component in the event listener
    once again thanks for all your great help
    Stu.
    ——————–
    Alex responds:
    If the exception is thrown in the listener, then you need to check the code in the listener. Just because you’ve used a subclass of DG shouldn’t change how you wrote that code. Maybe you reorganized the code in some way. You’ll get a faster response if you post your code and the full stacktrace with line numbers on the Adobe Flex Forum

  22. Stu says:

    Hi Alex
    this is following on from last nights question – after more troubleshooting it is not a DoubleClickDataGrid issue, it happens also with plain old DataGrid.
    the issue I have is in the application container I have a ViewStack, under the viewstack I had two canvas defined, the DataGrid was in the first canvas, in this scenario the AddEventListner works fine, the AddEventListner is in an AS function init() which is run onCompletion of the Application container.
    When I add a new canvas, even an empty one above the canvas containing the datagrid I immediately get the #1009 errors again.
    I am missing something I guess in my understanding of Flex framework but cannot work out what is happening…
    I know this is now off topic for DoubleClickDataGrid but if you can offer me a pointer through your experience it will be very much appreciated.
    thanks
    Stu.
    —————
    Alex responds:
    That sounds like you’ll need to read up on deferred instantiation and creationPolicy. We create viewstack items “just in time”. You’ll see many Forum posts on this topic

  23. ZUb says:

    Hi Alex, thank you for this very useful tip !

  24. Javier says:

    Jana, great solution to the doubleClickDatagrid! so simple and effective!
    Cheers!

  25. Henry Rabinowitz says:

    Hi Alex,
    I’m trying to do a similar thing but reversed: I want to have a doubleClick action on a List, but still allow single click to invoke editing. What happens instead is that doubleclick just invokes the itemEditor. Is there a way I can set a doubleClick handler on a list so that doubleClick will not trigger the itemEditor?
    –Henry

  26. Florian says:

    Hi Alex,
    Great !! Thanks.
    However, I’ve got a problem. The edit works very well when an item is double clicked, but I would like to call a function when a single click occurs. I’ve added a call to a function on the “itemClick” event of my datagrid, but the event is fired before a double click so now the double-click edit doesn’t work any more… Any ideas on how to separate both events correclty ? Thanks.

  27. Alex Harui says:

    I think you’ll have to disable editing on single-click, detect the click and if you don’t see a double-click within a certain amount of time, put up the editor by setting editedItemPosition. Once the editor goes up, the second click is on the editor so you won’t get a double-click

  28. Alex Harui says:

    Usually it is all timing. You have to wait to see if a double-click occurs before actually doing the action from the click.

  29. alibaba says:

    It doesn’t seem to work with darg and drop generally (not only with a tree component as Jeff Peck mentioned). When dropping, the dragged element goes to edit mode.

  30. Alex Harui says:

    Like I always say, caveats apply. These examples are unsupported. Hopefully you’ll find a way to fix it. I rarely have time to go back and update these posts.

  31. Alex says:

    Hi,
    Doesn’t work on mac (firefox 3.6) – the double click isn’t getting you into edit mode… Safari works fine…

  32. Gokulan V says:

    Hi Alex,
    Is there a way to edit a cell of an empty row?
    I am trying to add an item to the grid dynamically.
    Thanks,
    Gokul

  33. Gary says:

    Any idea how one would test this with flexunit to prove single click does nothing and double click edits? or is this only something I can see with a UI tester like Silk or Selenium?
    Thanks!

  34. Alex Harui says:

    Check out the “new entry” datagrid post.

  35. dl says:

    Hi,
    how do I disable that after I hit ENTER the next item to edit is being selected and in edit modus ?
    I just want that the edit stops after I hit Enter.
    Any help is welcome 🙂

  36. Alex Harui says:

    You should be able to use the ITEM_EDIT_* events to block future editing. Setting editedItemPosition to null should help.

  37. Sangee says:

    Hi,
    I am having a weird problem. I am allowing the users to edit the datagrid with the single click. I am using Itemrenderer and ItemEditor in my DG. All works fine as long as the DG doesn’t have a vertical scroll bar. i.e., as long as there aren’t many rows in the datagrid. When there is a vertical scroll bar and if I try to edit a row in the middle of the datagrid (when the vertical scroll bar is in the middle)it selects a different row instead of the selected row.
    Any help is highly appreciated. Thank you

  38. Alex Harui says:

    Try reproducing the problem in a regular DataGrid with default renderers and then start adding your custom renderers and editors until you start seeing the problem.

  39. Arodicus says:

    I could be off-base here but I think an easier method might be to simply trap a few events, rather than override the entire DataGrid and its methods:
    ——————————————————-
    <?xml version="1.0" encoding="utf-8"?>
    <s:Application xmlns:fx="http://ns.adobe.com/mxml/2009&#034;
           xmlns:s="library://ns.adobe.com/flex/spark"
              xmlns:mx="library://ns.adobe.com/flex/mx" minWidth="955" minHeight="600">

        <fx:Script>
          <![CDATA[
             import mx.events.DataGridEvent;
             import mx.events.ListEvent;
             private var dblClickEditMode:Boolean;
             
             [Bindable] private var dp:Array = [
                {Artist:"Pink Floyd", Price:"11.99", Album:"The Wall"},
                {Artist:"Pink Floyd", Price:"13.99", Album:"Animals"},
                {Artist:"Squeeze", Price:"12.99", Album:"Singles: 45’s and Under"},
                {Artist:"Squeeze", Price:"10.99", Album:"Some Fantastic Place"},
                ]
             
             protected function dgGrid_itemClick(event:ListEvent):void {
                dblClickEditMode=false;
             }
             protected function dgGrid_itemDoubleClick(event:ListEvent):void {
                dblClickEditMode=true;
             }   
             protected function dgGrid_itemEditBegin(event:DataGridEvent):void {
                if(!dblClickEditMode) event.preventDefault();
             }
             
          ]]>
       </fx:Script>
       
       <mx:DataGrid id="dgGrid"
                 editable="true"
                 doubleClickEnabled="true"
                 itemClick="dgGrid_itemClick(event)"
                 itemDoubleClick="dgGrid_itemDoubleClick(event)"
                 itemEditBegin="dgGrid_itemEditBegin(event)"
                 dataProvider="{dp}">
          <mx:columns>
             <mx:DataGridColumn dataField="Album"/>
             <mx:DataGridColumn dataField="Price"/>
          </mx:columns>
       </mx:DataGrid>
    </s:Application>
    ——————————————————-
    This seems to be a lot less invasive than a total rewrite… but again, there may be something I’m missing.

    • Arodicus says:

      Yup, I was missing something… my method is quick and dirty but fails if the guy using the component reassigns any of the event handlers; after looking at Alex’s code in more detail it’s apparent he’s already thought about that condition, hence the extra complexity.

      So while my method would work for simple projects and small team, it would fall apart as new developers would be added to the team. Use Alex’s version =)

  40. Baljeet says:

    The above totals works and is ridiculously simple ! Thanks Arodicus.

  41. vitaliy says:

    Hi and thank you for your examples.

    I had one question for a long time and did some test but couldn’t find an answer for it yet. So, the question is:

    how to turn all cells in particular row into edit mode when user clicks on any cell in this row?

    thanks

    • Alex Harui says:

      Well, you can’t make every cell in a row editable at the same time, but you could probably make the editor for a cell wide enough to cover all cells in the row and make it look like they are all editable