How to prevent closing of cell editing in ag-grid on "Other Cell Focus"
Asked Answered
S

3

6

I am working on an editable table in Angular application with ag-grid library. I would like to keep editing cells (in full row edit mode) until I finish with it and then close the editors manually via API. The problem is that the editor is closing on other cell click/focus (on some other line) as described here:

The grid will stop editing when any of the following happen:

  • Other Cell Focus: If focus in the grid goes to another cell, the editing will stop.

I cannot figure out how to disable this, if it is possible. Installing the onCellMouseDown() hook does not help, because the cellFocused event is fired before cellMouseDown. Therefore, the editing stops before I have a chance to intercept the mousedown event.

Here is my stackblitz little extract with related pieces of code.

The need for such scenario is that I want to validate the entry and not to allow a used to quit the editing if the form is not valid. The only workaround I found so far is that on any click outside of editing cells when the editor closing I reopen it right away in onRowEditingStopped() hook unless the editor has been closed via 'OK' button.

Schlosser answered 29/3, 2020 at 15:5 Comment(2)
I have used reactjs but this this.gridApi.redrawRows(); It helped me a little, although I still can't avoid focusing on another cell.Tiffinytiffy
I have exactly the same requirement...any update on this?Rodarte
R
2

After all, I have managed to provide a custom solution that fits exactly into this problem which I was facing also.

First thing is to disable pointer events to non edited rows when a specific row is currently being edited. On Ag-grid's 'cellEditingStarted' callback I have added the following code:

public cellEditingStarted(event: any): void {
    //not all rows are on dom ag-grid takes care of it
    const nonSelectedGridRows = document.querySelectorAll('.ag-grid-custom-row:not(.ag-row-selected):not(.ag-row-editing):not(.pointer-events-none)');

    forEach(nonSelectedGridRows, row => {
        row.classList.add("pointer-events-none");
    });
}

Because not all rows exist on dom (Ag-grid creates and destroys while you are scrolling )when a specific cell is being edited, I have also added a rowClassRule which is applied when rows are being created:

this.rowClassRules = {            
        'pointer-events-none': params => {
            if (params.api.getEditingCells().length > 0) {
                return true;
            }

            return false;
        }
    };

scss:

.pointer-events-none {
  pointer-events: none
}

By disabling pointer events, when you click on a non edited cell the cell won't get focus and thus the currently edited cell will stil remain on edit mode. You can provide your own custom validation solution and close the editor manually through API. When you are done, you have to enable pointer events to all grid rows back again:

private enablePointerEvents(): void {
    //not all rows are on dom ag-grid takes care of it
    const nonSelectedGridRows = document.querySelectorAll('.ag-grid-custom-row.pointer-events-none');

    forEach(nonSelectedGridRows, row => {
        row.classList.remove("pointer-events-none");
    });
}
Rodarte answered 21/9, 2020 at 5:48 Comment(2)
I was not able to implement what I want yet, but it looks like the right direction to dig intoSchlosser
Actually that's awful implemntation for Angular. Preferred solution would be integrating for the Overlays.Delete
M
1

Thought I would share another solution that has been working out okay for me so far.

Using 'pointer-events-none' as suggested in the other answer is flawed because the Enter key can also close the editor.

In my case, I want to prevent the editor from closing when client side validation has failed and the data is invalid. When my conditions are met, I call stopPropagation() on the events to prevent the editor close from happening in the first place. It still has potential problems:

  1. It cancels mousedown, dblclick, keydown, focusout and click for all elements that have a class name starting with ag- so if you happen to use this class prefix for other controls on the page, it could interfere. It also means any controls within the grid (sorting, resizing, etc.) don't work while the condition is met.
  2. Calling stopPropagation() could potentially interfere with your own custom controls. So far I've been okay if I dont use the ag- prefix within the markup from my own custom cell editors and renderers

I hope they can add a proper API function to cancel the row/cell stopEditing function in the future.

["mousedown", "dblclick", "keydown", "focusout", "click"].forEach(function (eventName) {
    document.addEventListener(eventName, function (e) {
        if ( conditionForCancelingIsMet() ) {
            // this appears to cancel some events in agGrid, it works for 
            // preventing editor closing on clicking other cells for example.
            // It would be ideal if this worked for all ag-grid specific events
            // and had a proper public API to use!
            e["__ag_Grid_Stop_Propagation"] = true;
        }

        // convert element classList to normal js array so we can use some()
        var classArray = [].slice.apply(e.target.classList);

        if ( conditionForCancelingIsMet() && classArray.some(c => c.startsWith("ag-")) ) {
            // unfortunately some events like pressing the 'enter' key still
            // require stopPropagation() and could potentially interfere with unrelated controls
            e.stopPropagation();
        }
    }, true);
});
Macronucleus answered 17/8, 2022 at 23:10 Comment(0)
M
0

I implemented the same above approach in Ag-Grid React. I used getRowStyle callback for adding the css pointerEvents: none on dynemic basis. It seems to be working for me fine. Please refer the below code

const getRowStyle = (params) => {
// this is not initialized in read mode
// condition for me ==> currentEditRowIndex.current !== null && params.node.rowIndex !== currentEditRowIndex.current
if (someCondition for Row other than inline edit row) {
  return { pointerEvents: "none" };
}
return null;
};

After adding this whenver you start the editing..You will need to call redrawRows so that css changes can be applied.

Hope this will help. Thank You!!

Masterpiece answered 27/7, 2021 at 15:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.