Blueprint: Using ContextMenu2 with table rows

Created on 5 Apr 2021  路  5Comments  路  Source: palantir/blueprint

With ContextMenu I had the ability to use "imperative" API when working with table rows:

Something like...

const handleContextMenu = (rowData: MyData) =>
  (): void => {
    // [1] Do something with rowData, like 'selectMyRow(rowData)' which then changes the rows color...
    // [2] Now show context menu
   ContextMenu.show(...)
};

<tr onContextMenu={handleContextMenu(rowData)}>
</tr>

How can I achieve something like that with ContextMenu2?

If I wrap entire table with ContextMenu2 then I would need to drill down using React/HTML API in order to get the data associated with the row I right-clicked on.

popover2 bug

Most helpful comment

Hm, you're right. I will need to spend some more time thinking about this... I'll make sure to figure out a way to support this use case before the final 4.0.0 release.

All 5 comments

did you try this?

const getRowContextMenuHandler = (rowData: MyData) => () => {
  // Do something with rowData, like 'selectMyRow(rowData)' which then changes the rows color...
};
const getRowContextMenu = (rowData: MyData) => {
  // return menu content here
};

return (
  <ContextMenu2 content={getRowContextMenu(rowData)} onContextMenu={getRowContextMenuHandler(rowData)}>
    <tr>{...}</tr>
  </ContextMenu2>
);

Given your example, and as I understand <ContextMenu2> from glancing at the source code - won't that produce invalid <table> markup, because each <tr> will be wrapped by <div>?

So instead of (which is valid HTML table markup):

<table>
  <tbody>
    <tr>...</tr> <!--  onContextMenu={handleContextMenu(rowData)} -->
    <tr>...</tr> <!--  onContextMenu={handleContextMenu(rowData)} -->
    <tr>...</tr> <!--  onContextMenu={handleContextMenu(rowData)} -->
    ...
  </tbody>
</table>

Your example would result in something like (which is invalid markup):

<table>
  <tbody>
    <div> <!-- This div is a result of `<ContextMenu2>` -->
      <tr>...</tr>
    </div>
    <div> <!-- This div is a result of `<ContextMenu2>` -->
      <tr>...</tr>
    </div>
    <div> <!-- This div is a result of `<ContextMenu2>` -->
      <tr>...</tr>
    </div>
    ...
  </tbody>
</table>

Also, wrapping each row with <ContextMenu2> fells like a overkill.

Ok, then you can try flipping the DOM ordering:

<tr>
  <ContextMenu2 ...>
</tr>

Also, wrapping each row with fells like a overkill.

By what metric? Each context menu has different information about the row, so this is fairly idiomatic React IMO. There may be a separate feature request here for having ContextMenu2 _not_ generate a wrapper element (similar to how Popover2's renderTarget prop lets you do the same), if you really want to simplify the DOM structure.

Ok, then you can try flipping the DOM ordering:

<tr>
  <ContextMenu2 ...>
</tr>

Won't that result in invalid HTML markup as well?

<tr>
  <div> <!-- This div is a result of `<ContextMenu2>` -->
    <td>Cell 1</td>
    <td>Cell 2</td>
    <td>Cell 3</td>
  </div>
</tr>

Hm, you're right. I will need to spend some more time thinking about this... I'll make sure to figure out a way to support this use case before the final 4.0.0 release.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

tomzaku picture tomzaku  路  3Comments

vinz243 picture vinz243  路  3Comments

giladgray picture giladgray  路  3Comments

havesomeleeway picture havesomeleeway  路  3Comments

westrem picture westrem  路  3Comments