Search code examples
ag-gridag-grid-angularag-grid-react

ag-Grid - show buttons on row hover like in Gmail


In ag-Grid, I want to show action buttons when a row is hovered like in Gmail. The action buttons have to appear at the right end of grid irrespective of scroll position.

There is one approach mentioned at https://blog.ag-grid.com/build-email-client-with-ag-grid-like-gmail/. They have used a cellRenderer on the last column and showed buttons in it when "onCellMouseOver" happens. This approach would work only if the last column (which uses cellRenderer) is always in view. If that column goes out of view, action buttons will also go out of view.

I cannot use this approach since in my case, there are many columns and all columns in my grid do not fit on the screen at the same time. So, there can be any column at the right end depending on scroll position and thus we don't know which column to add cellRenderer on.

enter image description here

How will we achieve this?


Solution

  • Here is a plunk that demonstrates my solution: https://plnkr.co/edit/X4hCimLy6aL3j4eh

    It turns out that this can be achieved using just CSS. Here is how I did it:

    1. Add a column for showing action buttons. Use cellRenderer to render buttons in it. Pin it to right.
    2. Using CSS,
      • absolute position the ag-pinned-right-cols-container to right
      • hide right header and spacer by setting their width 0
      • for rows which are not being hovered, hide action buttons cell in them by setting their padding & width 0

    Here is complete CSS with explanation:

    /* Hide right header and spacer */
    .ag-pinned-right-header,
    .ag-horizontal-right-spacer {
      width: 0 !important;
      min-width: 0 !important;
    }
    
    /* Add absolute position so that action buttons column will appear on top of other columns. 
       pointer-events: none to pass on mouse events to behind columns */
    .ag-pinned-right-cols-container {
      position: absolute !important;
      right: 0;
      pointer-events: none;
    }
    /* Reset pointer-events so that click can happen on action buttons */
    .ag-pinned-right-cols-container * {
      pointer-events: initial;
    }
    
    /* Hide border of right-cols-container */
    .ag-pinned-right-cols-container .ag-cell {
      border: none !important;
    }
    
    /* Show action buttons only for the row that is being hovered. 
       For rows which are not being hovered, hide them by setting their width and padding to 0. */
    .ag-pinned-right-cols-container .ag-row:not(.ag-row-hover),
    .ag-pinned-right-cols-container .ag-row:not(.ag-row-hover) .ag-cell {
      width: 0 !important;
      padding: 0 !important;
    }
    

    Ag-grid's default row hover and row selected colour has some transparency. Since our action buttons column is placed absolutely over other columns, its background looks darker because of the way those transparent colours blend.

    enter image description here

    So, it is better to use background colours with no transparency in this method like this:

    .ag-theme-alpine {
      --ag-row-hover-color: hsl(207, 90%, 94%);
      --ag-selected-row-background-color: hsl(207, 87%, 86%);
    }
    

    Overall,

    Pros:-

    1. It's a drop-in solution. You can just drop above CSS in your code and you will get the button on hover functionality.
    2. This approach is framework agnostic. I have tested it on React and Angular. (For Angular, you will have to use ng-deep to workaround style encapsulation)

    Cons:-

    1. This won't work if you already have one or more columns pinned to the right
    2. A future version of ag-grid might use different class names. So this CSS might need to be updated while upgrading ag-grid