简体   繁体   中英

Ag-grid Cell containing menu button

I am using community version of ag-grid in my project. I am trying add menu button in one of the cell of every row. on clicking of the menu button, there should be menu pop up, which will have Edit/delete/rename options and I need to fire event with row value when any item on menu is clicked.

I am trying to create a cell renderer which will display the button. menu will be hidden initially and on clicking of button, I am changing display using css class. I am seeing the css class is getting added correctly but the menu is still not visible. I checked in the console and it is hidden behind the table. I used position absolute and z-index at various place but ended up with no luck.

I can not use context menu or enterprise menu out of box as I am using community version. can you please help me here? also, is there any better way to achieve this result then let me know. Thanks a lot in advance.

var students = [
    {value: 14, type: 'age'},
    {value: 'female', type: 'gender'},
    {value: "Happy", type: 'mood'},
    {value: 21, type: 'age'},
    {value: 'male', type: 'gender'},
    {value: "Sad", type: 'mood'}
];


var columnDefs = [
    {
        headerName: "Value",
        field: "value",
        width: 100
    },

    {headerName: "Type", field: "type", width: 100},
     {headerName: "Action", width: 100, cellRenderer: 'actionMenuRenderer' }
];

var gridOptions = {
    columnDefs: columnDefs,
    rowData: students,
    onGridReady: function (params) {
        params.api.sizeColumnsToFit();
    },
    components:{
      actionMenuRenderer: ActionMenuCellRenderer
    }
};
function ActionMenuCellRenderer() {
}

ActionMenuCellRenderer.prototype.init = function (params) {
    this.eGui = document.createElement('div')

    if (params.value !== "" || params.value !== undefined || params.value !== null) {
         this.eGui.classList.add('menu');
         this.eGui.innerHTML = this.getMenuMarkup();
         this.actionBtn =  this.eGui.querySelector(`.actionButton`);
           this.menuWrapper =  this.eGui.querySelector(`.menuWrapper`);
           this.actionBtn.addEventListener('click', event => this.onActionBtnClick(event));
    }
};

ActionMenuCellRenderer.prototype.getGui = function () {
    return this.eGui;
};

ActionMenuCellRenderer.prototype.onActionBtnClick = function() {
    alert('hey');
    this.menuWrapper.classList.toggle('showMenu');
}

ActionMenuCellRenderer.prototype.getMenuMarkup = function () {
        return `
            <button type="button" class="actionButton">
              menu
            </button>
            <div class="menuWrapper">
                <a class="menuItem">
                    Edit
                </a>
                <a class="menuItem">
                    Delete
                </a>
                <a class="menuItem">
                    Duplicate
                </a>
            </div>
        `;
}

My plnkr sample- plnkr sample

The issue is due to the context menu also renders inside the ag-grid cell. So it does not matter how much z-index you give it can not display it outside the cell renderer div of the ag grid. The solution is we can use the library like Tippys which will render the menu outside the ag-grid main div which will fix the issue. Below is the sample code for react to show the menu on click of a button in ag-grid cell renderer.

There was nice blog by the ag-grid on the same. Here is the reference link

import React, { useState, useEffect, useMemo, useRef } from "react";
import { AgGridReact } from "ag-grid-react";
import Tippy from "@tippyjs/react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-alpine.css";

function ActionsMenu(props) {
  const tippyRef = useRef();
  const [visible, setVisible] = useState(false);

  const show = () => setVisible(true);
  const hide = () => setVisible(false);

  const menu = (
    <div className="menu-container">
      <div className="menu-item" onClick={hide}>
        Create
      </div>
      <div className="menu-item" onClick={hide}>
        Edit
      </div>
      <div className="menu-item" onClick={hide}>
        Delete
      </div>
    </div>
  );
  return (
    <Tippy
      ref={tippyRef}
      content={menu}
      visible={visible}
      onClickOutside={hide}
      allowHTML={true}
      arrow={false}
      appendTo={document.body}
      interactive={true}
      placement="right"
      // moveTransition='transform 0.1s ease-out'
    >
      <button onClick={visible ? hide : show}>Actions</button>
    </Tippy>
  );
}

const frameworkComponents = {
  ActionsMenu: ActionsMenu,
};

export default function App() {
  const [rowData, setRowData] = useState([
    { make: "Ford", model: "Focus", price: 20000 },
    { make: "Toyota", model: "Celica", price: 40000 },
    { make: "BMW", model: "4 Series", price: 50000 },
  ]);

  const [columnDefs, setColumnDefs] = useState([
    { field: "make" },
    { field: "model" },
    { field: "price" },
    { field: "", cellRenderer: "ActionsMenu" },
  ]);

  const defaultColDef = useMemo(
    () => ({
      sortable: true,
      filter: true,
    }),
    []
  );
  useEffect(() => {
    fetch("https://www.ag-grid.com/example-assets/row-data.json")
      .then((result) => result.json())
      .then((r) => setRowData(r));
  }, []);
  return (
    <div className="ag-theme-alpine" style={{ height: 500, width: "100%" }}>
      <AgGridReact
        rowData={rowData}
        columnDefs={columnDefs}
        defaultColDef={defaultColDef}
        frameworkComponents={frameworkComponents}
      />
    </div>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM