'How to to upload the context menu dynamically?

I am trying to upload row context menu dynamically but finally it does not show menu in the browser. My JS code:

async function getRowContextMenuFromServer(component, e) {
    // Get context menu data from server
    let id = component.getData().id;
    let url = "/api/" + id + "/context_menu/";
    let responce = await fetch(url);
    let data = await responce.json();
    let menu = parse_ui(data);
    return menu;
}

var table_bundle = new Tabulator("#table", {
    ajaxURL: "api/rows/,
    index: "id",
    movableRows: true,
    dataTree: true,
    dataTreeElementColumn: "name",
    dataTreeStartExpanded: true,
    dataTreeSelectPropagate: true,
    pagination: false,
    headerVisible: true,
    height: 500,
    layout: "fitData",
    dataTreeChildField: "children",
    rowContextMenu: getRowContextMenuFromServer,
    columns: [
        { title: "ID", field: 'id', visible: false },
        { title: "Name", field: 'name', headerFilter: true },
    ],
});

But it looks like browser shows menu before it is uploaded from server. When I create it as guide here menu is shown just fine.

What is the right way to get context menu dynamically from server?



Solution 1:[1]

You cannot do this with an ajax request, the rowContextMenu function must return the menu object straight away, it cannot handle async requests.

You would need to load the data from the sever when the table is loaded and then reference the local data when you want to build the menu

Solution 2:[2]

Finally I found the way how to get context menu dynamically from server:

  1. I catch event "rowContext"
  2. load context menu
  3. call internal Tabulator function table.modules.menu.loadMenu in order to show context menu.

Here is an example:

var table_bundle = new Tabulator("#table", {
  ajaxURL: "api/rows/,
  index: "id",
  movableRows: true,
  dataTree: true,
  dataTreeElementColumn: "name",
  dataTreeStartExpanded: true,
  dataTreeSelectPropagate: true,
  pagination: false,
  headerVisible: true,
  height: 500,
  layout: "fitData",
  dataTreeChildField: "children",
  columns: [
      { title: "ID", field: 'id', visible: false },
      { title: "Name", field: 'name', headerFilter: true },
  ],
});

table.on("rowContext", function(e, row){
  //e - the click event object
  //row - row component
  e.stopPropagation();
  e.preventDefault();
  let pk = row.getData().id
  fetch("api/contextmenu/" + pk)
      .then(function(responce) {
        return responce.json();
      })
      .then(function(data) {
         // in data - uploaded context menu for particular row
         // we call internal function in order to show context menu
         row.table.modules.menu.loadMenu(e, row, data);
      })
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Oli Folkerd
Solution 2