Context menu in data table

I have created a data table and for each row, I need a button with a sub menu.
I created the button, and the sub menu in one master because I need it in other data tables too.
Clicking the button shows a hidden group of items, with options flyout, bring to front.

Everything works, except that the row grows in height when the menu opens. How can I avoid that?

Is your table an actual Table widget, or is it a Repeater? If it is a repeater, you could try to uncheck the “Fit to Content in HTML” option in the STYLE panel (with the repeater selected on the page.) If your rows never change size, this should work.

Otherwise, Repeater or Table, keep the popup menu separate from your “data table”.

  • You’ll need to move the popup widget to right row when you show it.
  • For a repeater, you can do this by using the expression, Move MyPopup to ( , [[ + (This.bottom * Item.index)]] where LVAR1 points to the repeater, and you only need to move in the y-orientation. To move left-right you can apply this same method, referring to .left and right as needed.)
  • For a Table, use something like, Move MyPopup to ( , [[ + (This.bottom * MyIndexVar)]] where MyIndexVar is a global variable or text on a widget that refers to the row (and/or column) of the given cell. If you name the “(Table Cell Name)” properly, you could refer to that, as in [[]].

This is great, thank you.

Would have loved to keep the pop-up menu close to the button in the repeater row though.

I have kept the context menu separate from the repeater, but it is not aligning to the clicked item’s location. All I want to do is have a contextual menu popup every time the context icon is clicked, and each row would have link to the page where user should land. Thanks in advance for your help!

Perhaps an easier and more direct solution for this would be to move your context menu to the cursor’s location, like, Move MyContextMenu to ([[Cursor.x]], [[Cursor.y]])

So the item’s location is not being calculated properly. I think in my sample expression above I assumed the entire row would be clickable, rather than a specific widget within that row. To accommodate the latter, as well as the x-coordinate, a more full expression would look like:
Move MyContextMenu to ( [[LVAR1.x + This.x]],
[[LVAR1.y + ((LVAR2.height * (Item.index -1)) + This.bottom)]] )

  • Where LVAR1 is a local variable pointing to the repeater widget
  • LVAR2 is a local variable pointing to a widget which is the full height of the row
  • This is a built-in pointer to the widget triggering this event–the widget being clicked.
  • (All rows need to be the same height)

Here’s some background on how the method I describe above works–for a context menu separate from the repeater. Within a repeater cell (the widgets in each row) all coordinates are relative to that row’s cell, not relative to the page. So, to get the location of a widget in a row in a repeater, you need to:

  • Start with the location of the repeater (these are the LVAR1.x and LVAR1.y values.)
  • Then, calculate the row’s location in the repeater (the y-coordinate for vertical repeaters, the x-location for horizontal repeaters)–assuming all row’s have the same dimensions, you get this value with the expression, LVAR2.height * Item.index , where LVAR2 is a widget equivalent to the height of each row.
    • (Alternatively, you could refer to the bottom of the bottom-most widget in the row cell with LVAR2.bottom )
    • To get the top of each row, subtract 1 from Item.index before multiplying.
  • Then, calculate the widget’s coordinates within the row, using “This” as a relative pointer–assuming the positioning is relative to the widget which is clicked.
  • Likewise, the coordinates of widgets within a dynamic panel are relative to that dynamic panel. So, if your repeater is located inside a dynamic panel, you’ll need to start with the location of that dynamic panel (and so on if dynamic panel is nested within another dynamic panel), then add the location of the repeater, then location of the row, then location of a widget within the row.

Are all your rows the same height?

  • If not, the y-axis (vertical) location would be wrong–maybe for all but the first row.
  • You’d need a way to accommodate for each row’s height. This could be tricky if they are all different in unpredictable ways. Perhaps each row could calculate it’s own height in the Item Loaded event and store the cumulative result in a variable and/or hidden text widget in the repeater cell.

If you have a sample .rp file you could post, I could take a look and offer a tailored solution for you.

Thanks a lot @mbc66 for such a detailed explanation. I’ll try it out and hopefully it should work. Thanks again.