Add Custom Context Menus


You can create the custom menu items to enable users to run external actions, based upon the marks they’ve selected in a view. The context menu is added to the Uber tooltip that appears when users select marks, as shown in the following example.

Example of a custom context menu

The context menu is integrated into the view, and lets you provide users with seamless access to external actions that you choose.


In this section


Context menu methods

Starting with version 3.2 of the Embedding API 3.2 library, you can use the following methods to add or remove custom context menu items. For information about each method, click on the links.

Method Description
appendContextMenuAsync Adds a new menu item.
renameContextMenuAsync Renames the menu header. The default name is Embedded.
removeContextMenuAsync Removes the context menu and menu item.

The following section shows the steps you go through to add a menu item to the Uber tooltip and then tie that menu item to drive an external action.

Add a custom context menu item

To add a custom context menu item, use the Worksheet.appendContextMenuAsync() method.

The method takes two parameters. The first specifies the location of the context menu. In this case, it is ApiMenuType.Ubertip, the only location currently supported.

The second parameter specifies the context menu options and specifies the text that appears for the menu item. If the method succeeds, it returns the identifier for the menu item that was added. You use this identifier to remove the menu item or to know which menu item was clicked.

For example, the following code snippet adds a menu item called “Run my app.” The ID returned by the appendContextMenuAsync method and the name of the menu item are mapped and stored in an array.


   // The following assumes that you are calling this code from an `async`
   // function. 
     ...

    const menuItemName = "Run my app";
    const config = { displayName: menuItemName };
    const menuItemMap = {}; // Stores identifiers of newly inserted context menu items
    try {
          const menuItemId = await worksheet.appendContextMenuAsync(ApiMenuType.Ubertip, config);
          menuItemMap[menuItemName] = menuItemId;
       } catch (e) {
           alert("An exception was thrown: " + e);
       } finally {
           return;
       }
     ... 

Rename the default menu header

By default, the menu heading in the Uber tip says “Embedded.” To change this to something that is more descriptive of the menu item(s) that you are adding, use the Worksheet.renameContextMenuAsync() method.

In this case, the code snippet shows how you change the name of the menu header to “Actions” from “Embedding” (the default heading). You can use the menuDescription to provide a tooltip for the menu.


   // The following assumes that you are calling this code from an `async`
   // function.
   ...

   const menuName = "Actions";
   const menuDescription = "Run custom actions";

   try {
       await worksheet.renameContextMenuAsync(ApiMenuType.Ubertip, menuName, menuDescription);
   } catch (e) {
       alert("An exception was thrown: " + e);
   } finally {
       return;
   }

   ...

Add an event listener for the custom context menu item

Add an event listener and create an event handler for your custom menu item. You need to specify the event type as a TableauEventType.CustomMarkContextMenuEvent. The following code snippet specifies an event handler, called customMarkEventHandler, to take action when someone clicks the context menu item.

   ...

   // Add the event listener
   viz.addEventListener(TableauEventType.CustomMarkContextMenuEvent, customMarkEventHandler);

   ...
   

Create the event handler for the menu item

When the event occurs, the event handler is called and it takes the CustomMarkContextMenuEvent as a parameter. From the details of CustomMarkContextMenuEvent, you can get the identifier for the menu item that was clicked and the marks that were selected. You can use this information to take further action. In this example, the action is to call another method (displaySelectedMarks) that displays information about the selected marks. In your own code, you could use the selected data to call into another application or to drive actions within your web application.

   
   // Get the context menu id

   function setMenuItemId(customMarkContextMenuEvent) {
       contextMenuId = customMarkContextMenuEvent.detail.getContextMenuId();
   }
   
   function getMenuItemId() {
       return contextMenuId;
   }

   // define the event handler for the context menu item

   function customMarkEventHandler(customMarkContextMenuEvent) {
       console.log("Reached the customMarkContextMenuEvent");
       // check the context menu id and run custom actions with the marks selected
       setMenuItemId(customMarkContextMenuEvent);

       return customMarkContextMenuEvent.detail.getSelectedMarksAsync().then(displaySelectedMarks);
   } 

   // example action that shows how to process display the marks 

   function displaySelectedMarks(marks) {
     const html = [];

     for (let markIndex = 0; markIndex < marks.data[0].data.length; markIndex++) {
       const columns = marks.data[0].columns;
       html.push(`<b>Mark ${markIndex}</b>, MenuId ${getMenuItemId()}:</b><ul>`);

       for (let colIndex = 0; colIndex < columns.length; colIndex++) {
          html.push(`<li><b>Field Name:</b> ${columns[colIndex].fieldName}`);
          html.push(`<br/><b>Value:</b> ${marks.data[0].data[markIndex][colIndex].formattedValue}</li>`);
        }
        html.push("</ul>");

        const infoDiv = document.getElementById("markDetails");
        infoDiv.innerHTML = html.join('');
     }
   }