# Ui-table row contextmenu doesn't work?

**URL:** https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851
**Category:** Dashboard
**Tags:** node-red-dashboard
**Created:** [8 December 2021 02:35 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851 "2021-12-08T02:35:30Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![Henjoe](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/henjoe/32/52335_2.png) [@Henjoe](https://discourse.nodered.org/u/Henjoe)
#### Post date: [8 December 2021 02:35 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/1 "2021-12-08T02:35:30Z")

</div>

Hello, I am trying to add Context menu on node-red-ui-table using the msg.ui\_control as seen below:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/f/6f3783655249c4a1fbbc596fa6cf96f7ae7d5e06.png)

However, It doesn't work when I right-clicked on my table.

As per Tabulator's manual:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/4/e/4e8b2ab097d9a942e781ca137db366f412d979d5.png)

I don't know what I did wrong. Hoping for your guidance. or a confirmation if it is not possible on this table?

Thank you Node-red experts 🙂  
Regards,  
Henjoe

---

<div class="post-metadata">

### Author: ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)
#### Post date: [8 December 2021 09:56 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/2 "2021-12-08T09:56:33Z")

</div>

Hi,

you did nothing wrong (beside the action should be a callback function) but ui-table uses the now [outdated version 4.4.1 of tabulator](https://github.com/node-red/node-red-ui-nodes/blob/master/node-red-node-ui-table/lib/js/tabulator.js#:~:text=/*%20Tabulator%20v4.4.1%20(c)%20Oliver%20Folkerd%20*/) which **does not have the menue feature**. (If you use the docs make shure that you are on version 4.4)

There is already an [issue posted](https://github.com/node-red/node-red-ui-nodes/issues/72) to update to 5.0 but I have no time in the near feature to contribute this (My first try revealed a lot of API changes and new problems).

I'm using the ui-context menue node to do so and even if it brings more effort you get Node-RED in control of the context menu. The [post you already found is still valid]. And there is a `cellCotext` and a `rowContext` callback too. ([[Announce] node-red-contrib-ui-contextmenu - #55 by Christian-Me](https://discourse.nodered.org/t/announce-node-red-contrib-ui-contextmenu/16211/55))

Here is a partial flow to handle the ui-context-menu. It works together with the callback described in the post above

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/9/7/979e86243407ed6b80d8081f46a50436c50f6eef.png)

I'll could not promise anything but I'm still willing to do the upgrade to 5.x - but there are so many possibilities to break things - so I'm a little bit afraid to do this in a rush.

```auto
[{"id":"fd36bbc4.fe50d8","type":"subflow","name":"OK/Cancel helper","info":"# OK/Cancel dialog helper\n\n## description\n\nThis is a little helper to make OK/Cancel dialogs easy to implement inside a data stream\n\n## how it works\n\nIf a message arrives at the **imput** a message dialog box is triggered. The original Message is cloned into `msg.dialogHelperOrgMsg`. If the dialog sends `msg.payload` with the **passPayload** the original message is released on the second output.\n\nIf you use the message node \"with input\" enter your cancel payload instead pass payload as `msg.payload` will include the entered text.\n\nmake shure you pass `msg.socketid`of the session you like the dialog to be displayed.\n\n## configuration\n\n- **Title** *optional* a string displayed on the title of the dialog or `msg.dialogTitle`\n- **Message** message to be displayed or `msg.dialogMessage`\n- **passPayload** the `msg.payload` expected on the imput to release to original message.\n- **cancelPayload** if this subflow is used for text imput dialogs enter your cancel payload instead pass payload als `msg.payload` will include the ented text.","category":"","in":[{"x":37,"y":85,"wires":[{"id":"6a44f1d4.72a75"}]}],"out":[{"x":343,"y":85,"wires":[{"id":"6a44f1d4.72a75","port":1}]},{"x":343,"y":136,"wires":[{"id":"6a44f1d4.72a75","port":2}]}],"env":[{"name":"title","type":"str","value":"Please Confirm","ui":{"icon":"font-awesome/fa-comment","label":{"en-US":"Title"},"type":"input","opts":{"types":["str","env"]}}},{"name":"message","type":"str","value":"should the message pass on?","ui":{"icon":"font-awesome/fa-comment-o","label":{"en-US":"Message"},"type":"input","opts":{"types":["str","env"]}}},{"name":"passPayload","type":"str","value":"OK","ui":{"icon":"font-awesome/fa-check-square-o","type":"input","opts":{"types":["str","env"]}}},{"name":"cancelPayload","type":"str","value":"Cancel"}],"color":"#3FADB5","icon":"font-awesome/fa-comments-o","status":{"x":343,"y":34,"wires":[{"id":"6a44f1d4.72a75","port":0}]}},{"id":"6a44f1d4.72a75","type":"function","z":"fd36bbc4.fe50d8","name":"confirm","func":"var status={fill:\"\",shape:\"dot\",text:\"\"};\nif (msg!==undefined && !msg.hasOwnProperty(\"dialogHelperOrgMsg\")) { // no message in queue\n var dialogMsg={\n topic:(msg.dialogTitle) ? msg.dialogTitle : env.get('title'),\n payload:(msg.dialogMessage) ? msg.dialogMessage : env.get('message'),\n socketid:msg.socketid,\n dialogHelperOrgMsg:RED.util.cloneMessage(msg)\n };\n status={fill:\"yellow\",shape:\"dot\",text:\"waiting for response\"};\n return [{payload:status},dialogMsg,null];\n} else {\n var cancelPayload=env.get('cancelPayload').toLowerCase();\n var passPayload=env.get('passPayload').toLowerCase();\n if (passPayload!=='') {\n if (msg.payload.toLowerCase()===passPayload) {\n status={fill:\"green\",shape:\"dot\",text:\"message passed\"};\n return [{payload:status},null,msg.dialogHelperOrgMsg];\n } else {\n status={fill:\"blue\",shape:\"dot\",text:msg.payload+\"==(!\"+passPayload+\") message droped\"};\n return [{payload:status},null,null];\n }\n } else if (cancelPayload!=='') {\n if (msg.payload.toLowerCase()!==cancelPayload) {\n status={fill:\"green\",shape:\"dot\",text:\"message passed\"};\n msg.dialogHelperOrgMsg.payload=msg.payload; // add input to msg.payload\n return [{payload:status},null,msg.dialogHelperOrgMsg];\n } else {\n status={fill:\"blue\",shape:\"dot\",text:msg.payload+\"==(\"+cancelPayload+\") message droped\"};\n return [{payload:status},null,null];\n } \n } else {\n status={fill:\"red\",shape:\"dot\",text:\"pass or cancel payload undefined\"};\n return [{payload:status},null,null];\n }\n}","outputs":3,"noerr":0,"initialize":"","finalize":"","x":196,"y":85,"wires":[[],[],[]],"info":"# OK/Cancel dialog helper function\n\n## description\n\nThis is a little helper to make OK/Cancel dialogs easy to implement inside a data stream\n\n## how it works\n\nIf a message arrives at the **imput** a message dialog box is triggered. The original Message is cloned into `msg.dialogHelperOrgMsg`. If the dialog sends `msg.payload` with the **passPayload** the original message is released on the second output.\n\n## envioment variables\n\n- **title**  ***optional** a string displayed on the title of the dialog\n- **message** message to be displayed\n- **passPayload** the `msg.payload` expected on the imput to release to original message."},{"id":"e6740516.9b1688","type":"switch","z":"9d52d40a.a63668","name":"callback","property":"ui_control.callback","propertyType":"msg","rules":[{"t":"eq","v":"rowContext","vt":"str"},{"t":"eq","v":"headerContext","vt":"str"},{"t":"eq","v":"cellEdited","vt":"str"},{"t":"eq","v":"columnMoved","vt":"str"},{"t":"eq","v":"columnResized","vt":"str"}],"checkall":"false","repair":false,"outputs":5,"x":179,"y":1530,"wires":[["5bf60e7.23625f"],["f246c2d4.aa89c"],[],[],[]]},{"id":"749057bc.c4a6d8","type":"switch","z":"9d52d40a.a63668","name":"","property":"payload.command","propertyType":"msg","rules":[{"t":"eq","v":"updateDevice","vt":"str"},{"t":"eq","v":"updateDevices","vt":"str"},{"t":"eq","v":"deleteDevice","vt":"str"},{"t":"eq","v":"ignoreDevice","vt":"str"},{"t":"eq","v":"unIgnoreDevice","vt":"str"},{"t":"eq","v":"refreshTable","vt":"str"},{"t":"eq","v":"deleteTable","vt":"str"},{"t":"eq","v":"columnHide","vt":"str"},{"t":"eq","v":"columnsUnHide","vt":"str"},{"t":"eq","v":"columnUnHide","vt":"str"},{"t":"eq","v":"restoreColumnOrder","vt":"str"},{"t":"eq","v":"resetColumnWidth","vt":"str"},{"t":"eq","v":"setResponsiveLayout","vt":"str"}],"checkall":"false","repair":false,"outputs":13,"x":781,"y":1530,"wires":[["28af0304.acdeec"],["28af0304.acdeec"],["c59b8c64.16dc7"],["c59b8c64.16dc7"],["c59b8c64.16dc7"],["c59b8c64.16dc7"],["710ae3ea.b5244c"],["c59b8c64.16dc7"],["c59b8c64.16dc7"],["c59b8c64.16dc7"],["c59b8c64.16dc7"],["c59b8c64.16dc7"],["c59b8c64.16dc7"]]},{"id":"c59b8c64.16dc7","type":"link out","z":"9d52d40a.a63668","name":"toTable","links":["b1750dea.ac9c2","7d2b1b0d.058af4"],"x":950,"y":1530,"wires":[]},{"id":"28af0304.acdeec","type":"link out","z":"9d52d40a.a63668","name":"toAquire","links":["bfbc2876.2e7748","82fc1784.d3c078"],"x":950,"y":1445,"wires":[]},{"id":"13055b32.2932e5","type":"link out","z":"9d52d40a.a63668","name":"toPlugins","links":["b563fdad.d0b7c"],"x":1171,"y":1683,"wires":[]},{"id":"418512d5.1f8b6c","type":"function","z":"9d52d40a.a63668","name":"rowCommand","func":"// as this feeds back to the beginning of the flow it is time for a new message object\n// otherwise new and old data mix\n// all command data fills into a payload so it would unlikly survice verry long ;)\n\nvar msgOut={};\nswitch (msg.topic){\n case 'unIgnoreDevice':\n msgOut={\n topic:msg.payload,\n payload:{\n \"command\":msg.topic,\n \"object\":msg.payload\n }\n };\n break;\n case 'deleteTable':\n case 'updateDevice':\n case 'deleteDevice':\n case 'ignoreDevice':\n msgOut={\n topic:msg.sourceMsg.topic,\n socketid:msg.socketid,\n payload:{\n \"command\":msg.topic,\n \"object\":msg.sourceMsg.topic,\n \"$localip\":msg.sourceMsg.payload.$localip,\n \"$name\":msg.sourceMsg.payload.$name,\n \"name\":msg.sourceMsg.payload.name\n }\n };\n break;\n default:\n msgOut={\n topic:msg.sourceMsg.rowData.$topic,\n payload:{\n \"command\":msg.topic,\n \"object\":msg.sourceMsg.$topic,\n \"$localip\":msg.sourceMsg.payload.$localip,\n \"$name\":msg.sourceMsg.payload.$name,\n \"name\":msg.sourceMsg.payload.name,\n }\n }\n}\nnode.status({fill:\"green\",shape:\"dot\",text:msgOut.payload.command});\nreturn msgOut;","outputs":1,"noerr":0,"x":607,"y":1513,"wires":[["749057bc.c4a6d8","61b6cd67.e87d74"]]},{"id":"4b103b82.d5f934","type":"function","z":"9d52d40a.a63668","name":"colCommand","func":"// as this feeds back to the beginning of the flow it is time for a new message object\n// otherwise new and old data mix\n// all command data fills into a payload so it would unlikly survice verry long ;)\n\nvar msgOut={\n topic:\"columnRightClick\",\n payload:{\n \"command\":msg.topic,\n \"object\":msg.payload\n }\n}\n\n// some commands need the column from the prosition where the context menu was triggered\n\nswitch (msg.topic){\n case \"columnHide\":\n msgOut.payload.object=msg.sourceMsg.payload;\n break;\n}\nnode.status({fill:\"green\",shape:\"dot\",text:msgOut.payload.command});\nreturn msgOut;","outputs":1,"noerr":0,"x":614,"y":1564,"wires":[["749057bc.c4a6d8","b6f10d4c.dde98"]]},{"id":"430f3c7c.5622d4","type":"ui_context_menu","z":"9d52d40a.a63668","group":"3e8e6acd.3587c6","order":1,"width":0,"height":-1,"fontSize":16,"position":"msg","xCoordinate":"500","yCoordinate":"450","menu":"msg","outputField":"payload","menuItems":[{"id":"2","icon":"fa-plus-square","label":"unhide all columns","topic":"columnsUnHide","payload":"","payloadType":"str","visible":true,"enabled":true},{"id":"3","icon":"fa-recycle","label":"refresh Table","topic":"refreshTable","payload":"","payloadType":"str","visible":true,"enabled":true},{"id":"4","icon":"fa-table","label":"delete table","topic":"deleteTable","payload":"","payloadType":"str","visible":true,"enabled":true}],"colors":"theme","textColor":"#000000","backgroundColor":"#ffffff","borderColor":"#626262","intervalLength":"2","intervalUnit":"secs","startTimerAtOpen":false,"startTimerAtLeave":true,"stopTimerAtEnter":true,"name":"msgBased","x":410,"y":1615,"wires":[["4b103b82.d5f934"]]},{"id":"f246c2d4.aa89c","type":"function","z":"9d52d40a.a63668","name":"build column menu","func":"msg.menu=[\n {\n \"text\": \"update devices\",\n \"icon\": \"fa-undo\",\n \"enabled\": true,\n \"topic\": \"updateDevices\",\n },\n {\n \"text\": \"---\"\n },\n {\n \"text\": \"hide column\",\n \"icon\": \"fa-minus-square\",\n \"enabled\": true,\n \"topic\": \"columnHide\",\n },\n {\n \"text\": \"unhide column\",\n \"icon\": \"fa-minus-square-o\",\n \"enabled\": (msg.hiddenColumns.length>0) ? true : false,\n \"sub\": msg.hiddenColumns\n },\n {\n \"text\": \"unhide all columns\",\n \"icon\": \"fa-minus-square\",\n \"enabled\": true,\n \"topic\": \"columnsUnHide\",\n },\n {\n \"text\": \"---\"\n },\n {\n \"text\": \"restore column order\",\n \"icon\": \"fa-sort fa-rotate-90\",\n \"enabled\": true,\n \"topic\": \"restoreColumnOrder\"\n },\n {\n \"text\": \"reset column width\",\n \"icon\": \"fa-arrows-h\",\n \"enabled\": true,\n \"topic\": \"resetColumnWidth\"\n },\n {\n \"text\": \"rersponsive layout\",\n \"icon\": \"fa-mobile\",\n \"enabled\": true,\n \"topic\": \"setResponsiveLayout\"\n },\n {\n \"text\": \"refresh table\",\n \"icon\": \"fa-recycle\",\n \"enabled\": true,\n \"topic\": \"refreshTable\"\n },\n {\n \"text\": \"clear table\",\n \"icon\": \"fa-trash\",\n \"enabled\": true,\n \"topic\": \"deleteTable\"\n }\n];\n\nreturn msg;","outputs":1,"noerr":0,"x":379,"y":1564,"wires":[["430f3c7c.5622d4","90341f51.c352c"]]},{"id":"f9962a15.0fb1e8","type":"comment","z":"9d52d40a.a63668","name":"callbacks & context menus","info":"","x":229,"y":1411,"wires":[]},{"id":"5bf60e7.23625f","type":"function","z":"9d52d40a.a63668","name":"build row menu","func":"msg.menu=[\n {\n \"text\": \"update device\",\n \"icon\": \"fa-undo\",\n \"enabled\": true,\n \"topic\": \"updateDevice\",\n },\n {\n \"text\": \"---\"\n },\n {\n \"text\": \"delete device\",\n \"icon\": \"fa-trash\",\n \"enabled\": true,\n \"topic\": \"deleteDevice\",\n },\n {\n \"text\": \"ignore device\",\n \"icon\": \"fa-minus-square-o\",\n \"enabled\": true,\n \"topic\": \"ignoreDevice\",\n },\n {\n \"text\": \"unignore devices\",\n \"icon\": \"fa-plus-square-o\",\n \"enabled\": (msg.ignoredDevices.length>0) ? true : false,\n \"sub\": msg.ignoredDevices\n },\n {\n \"text\": \"unignore all devices\",\n \"icon\": \"fa-plus-square\",\n \"enabled\": true,\n \"topic\": \"unIgnoreDevices\",\n },\n {\n \"text\": \"---\"\n },\n {\n \"text\": \"refresh table\",\n \"icon\": \"fa-recycle\",\n \"enabled\": true,\n \"topic\": \"refreshTable\"\n },\n {\n \"text\": \"clear table\",\n \"icon\": \"fa-trash\",\n \"enabled\": true,\n \"topic\": \"deleteTable\"\n }\n];\n\nreturn msg;","outputs":1,"noerr":0,"x":369,"y":1462,"wires":[["19e8fb55.948665","4b6a4466.69800c"]]},{"id":"19e8fb55.948665","type":"ui_context_menu","z":"9d52d40a.a63668","group":"3e8e6acd.3587c6","order":1,"width":0,"height":-1,"fontSize":16,"position":"msg","xCoordinate":"500","yCoordinate":"450","menu":"msg","outputField":"payload","menuItems":[{"id":"2","icon":"fa-plus-square","label":"unhide all columns","topic":"columnsUnHide","payload":"","payloadType":"str","visible":true,"enabled":true},{"id":"3","icon":"fa-recycle","label":"refresh Table","topic":"refreshTable","payload":"","payloadType":"str","visible":true,"enabled":true},{"id":"4","icon":"fa-table","label":"delete table","topic":"deleteTable","payload":"","payloadType":"str","visible":true,"enabled":true}],"colors":"theme","textColor":"#000000","backgroundColor":"#ffffff","borderColor":"#626262","intervalLength":"2","intervalUnit":"secs","startTimerAtOpen":false,"startTimerAtLeave":true,"stopTimerAtEnter":true,"name":"msgBased","x":410,"y":1513,"wires":[["418512d5.1f8b6c"]]},{"id":"ab78269b.859828","type":"link in","z":"9d52d40a.a63668","name":"callbacksIn","links":["69cccd2b.cae4c4"],"x":66,"y":1530,"wires":[["e6740516.9b1688","620ab579.114dbc"]]},{"id":"b6f10d4c.dde98","type":"debug","z":"9d52d40a.a63668","name":"colCommand","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":801,"y":1649,"wires":[]},{"id":"61b6cd67.e87d74","type":"debug","z":"9d52d40a.a63668","name":"rowCommand","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":811,"y":1411,"wires":[]},{"id":"620ab579.114dbc","type":"debug","z":"9d52d40a.a63668","name":"callback","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":179,"y":1598,"wires":[]},{"id":"edbc167b.5a5748","type":"ui_toast","z":"9d52d40a.a63668","position":"dialog","displayTime":"3","highlight":"","sendall":false,"outputs":1,"ok":"OK","cancel":"Cancel","raw":false,"topic":"","name":"OK / Cancel","x":1226,"y":1598,"wires":[["710ae3ea.b5244c"]]},{"id":"4b6a4466.69800c","type":"debug","z":"9d52d40a.a63668","name":"rowMenu","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":587,"y":1462,"wires":[]},{"id":"90341f51.c352c","type":"debug","z":"9d52d40a.a63668","name":"rowMenu","active":false,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":587,"y":1615,"wires":[]},{"id":"710ae3ea.b5244c","type":"subflow:fd36bbc4.fe50d8","z":"9d52d40a.a63668","name":"delete Table?","env":[{"name":"message","value":"Do you realy whant to delete the complete table and all statistics. Cell edits and layout will be preserved.","type":"str"}],"x":1047,"y":1649,"wires":[["edbc167b.5a5748"],["13055b32.2932e5"]]},{"id":"3e8e6acd.3587c6","type":"ui_group","name":"Remote Device Table","tab":"dc3e656c.bbd048","order":2,"disp":false,"width":"19","collapse":false},{"id":"dc3e656c.bbd048","type":"ui_tab","name":"Remote Device Table","icon":"dashboard","order":22,"disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

### Author: ![Henjoe](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/henjoe/32/52335_2.png) [@Henjoe](https://discourse.nodered.org/u/Henjoe)
#### Post date: [8 December 2021 10:47 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/3 "2021-12-08T10:47:44Z")

</div>

Thanks my friend @Christian-Me, I will try this and will get back here once done.  
Highly appreciated your efforts.

Keep it up!

Regards,  
Henjoe

---

<div class="post-metadata">

### Author: ![Henjoe](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/henjoe/32/52335_2.png) [@Henjoe](https://discourse.nodered.org/u/Henjoe)
#### Post date: [8 December 2021 10:58 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/4 "2021-12-08T10:58:21Z")

</div>

Hi @Christian-Me , apologies, but I got confused on your sample.

Do you have a sample flow where I can see how to use this subflow:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/a/dad60dd1a024257f74be48c95813f56f682f20ec.png)

Thanks!

Regards,  
Henjoe

---

<div class="post-metadata">

### Author: ![Henjoe](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/henjoe/32/52335_2.png) [@Henjoe](https://discourse.nodered.org/u/Henjoe)
#### Post date: [8 December 2021 11:18 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/5 "2021-12-08T11:18:13Z")

</div>

Hi @Christian-Me , I get it now! 🙂

Thanks for your help!  
node-red-ui-contextmenu is the key in here, just need that X and Y position. 🙂

Again!

Thanks for your help!

Regards,  
Henjoe

---

<div class="post-metadata">

### Author: ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)
#### Post date: [8 December 2021 20:57 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/6 "2021-12-08T20:57:02Z")

</div>

Do you still need help for the notification helper subflow? This is handy to work with popup alert and input windows.

---

<div class="post-metadata">

### Author: ![Henjoe](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/henjoe/32/52335_2.png) [@Henjoe](https://discourse.nodered.org/u/Henjoe)
#### Post date: [8 December 2021 22:37 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/7 "2021-12-08T22:37:23Z")

</div>

Hi Christian,

Might as well can I have samples on how to use this helper subflow. Sounds interesting 🙂

Thank you!

---

<div class="post-metadata">

### Author: ![Christian-Me](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/christian-me/32/10774_2.png) [@Christian-Me](https://discourse.nodered.org/u/Christian-Me)
#### Post date: [9 December 2021 23:46 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/8 "2021-12-09T23:46:33Z")

</div>

Sure.

The task is to hold up a message until the user confirms to proceed.

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/0/b0c7d4d620c2019695c1f62a3dd5791a051ca447.png)

the subflow is configured like this

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/1/518a0c1111a6c24eb93938706afcce084e51cf2c.png)

the connected message node like this

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/0/d003339099de74660f152830efbce9dfa946a36c.png)

How it works:

The subflow packs the incoming message into a new message to the message node and sets the title and display text. If the `passPayload` equals the result OR the `cancelPayload` is not equal the result the original (incoming) message is sent out the second output.

Beside the subflow config dialog you can send `msg.dialogTitle` and `msg.dialogMessage` with the incoming message. If a `socketid` is passed the dialog opens only on this client.

Note: If a second message arrives before the first is confirmed the first is message is dropped and a new popup opens.

So an easy reusable way to stop messages until the user confirms to pass. Perhaps it is useful for others too.

Here is a test flow, have fun:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/6/b60256c0517968e0d550d52b0cca18b431b4d1cf.png)

```auto
[{"id":"fd36bbc4.fe50d8","type":"subflow","name":"OK/Cancel helper","info":"# OK/Cancel dialog helper\n\n## description\n\nThis is a little helper to make OK/Cancel dialogs easy to implement inside a data stream\n\n## how it works\n\nIf a message arrives at the **imput** a message dialog box is triggered. The original Message is cloned into `msg.dialogHelperOrgMsg`. If the dialog sends `msg.payload` with the **passPayload** the original message is released on the second output.\n\nIf you use the message node \"with input\" enter your cancel payload instead pass payload as `msg.payload` will include the entered text.\n\nmake shure you pass `msg.socketid`of the session you like the dialog to be displayed.\n\n## configuration\n\n- **Title** *optional* a string displayed on the title of the dialog or `msg.dialogTitle`\n- **Message** message to be displayed or `msg.dialogMessage`\n- **passPayload** the `msg.payload` expected on the imput to release to original message.\n- **cancelPayload** if this subflow is used for text imput dialogs enter your cancel payload instead pass payload als `msg.payload` will include the ented text.","category":"","in":[{"x":37,"y":85,"wires":[{"id":"6a44f1d4.72a75"}]}],"out":[{"x":343,"y":85,"wires":[{"id":"6a44f1d4.72a75","port":1}]},{"x":343,"y":136,"wires":[{"id":"6a44f1d4.72a75","port":2}]}],"env":[{"name":"title","type":"str","value":"Please Confirm","ui":{"icon":"font-awesome/fa-comment","label":{"en-US":"Title"},"type":"input","opts":{"types":["str","env"]}}},{"name":"message","type":"str","value":"should the message pass on?","ui":{"icon":"font-awesome/fa-comment-o","label":{"en-US":"Message"},"type":"input","opts":{"types":["str","env"]}}},{"name":"passPayload","type":"str","value":"OK","ui":{"icon":"font-awesome/fa-check-square-o","type":"input","opts":{"types":["str","env"]}}},{"name":"cancelPayload","type":"str","value":"Cancel"}],"color":"#3FADB5","icon":"font-awesome/fa-comments-o","status":{"x":343,"y":34,"wires":[{"id":"6a44f1d4.72a75","port":0}]}},{"id":"6a44f1d4.72a75","type":"function","z":"fd36bbc4.fe50d8","name":"confirm","func":"var status={fill:\"\",shape:\"dot\",text:\"\"};\nif (msg!==undefined && !msg.hasOwnProperty(\"dialogHelperOrgMsg\")) { // no message in queue\n var dialogMsg={\n topic:(msg.dialogTitle) ? msg.dialogTitle : env.get('title'),\n payload:(msg.dialogMessage) ? msg.dialogMessage : env.get('message'),\n socketid:msg.socketid,\n dialogHelperOrgMsg:RED.util.cloneMessage(msg)\n };\n status={fill:\"yellow\",shape:\"dot\",text:\"waiting for response\"};\n return [{payload:status},dialogMsg,null];\n} else {\n var cancelPayload=env.get('cancelPayload').toLowerCase();\n var passPayload=env.get('passPayload').toLowerCase();\n if (passPayload!=='') {\n if (msg.payload.toLowerCase()===passPayload) {\n status={fill:\"green\",shape:\"dot\",text:\"message passed\"};\n return [{payload:status},null,msg.dialogHelperOrgMsg];\n } else {\n status={fill:\"blue\",shape:\"dot\",text:`${msg.payload}!==\"${passPayload}\" message droped`};\n return [{payload:status},null,null];\n }\n } else if (cancelPayload!=='') {\n if (msg.payload.toLowerCase()!==cancelPayload) {\n status={fill:\"green\",shape:\"dot\",text:\"message passed\"};\n msg.dialogHelperOrgMsg.payload=msg.payload; // add input to msg.payload\n return [{payload:status},null,msg.dialogHelperOrgMsg];\n } else {\n status={fill:\"blue\",shape:\"dot\",text:`${msg.payload}==\"${cancelPayload}\") message droped`};\n return [{payload:status},null,null];\n } \n } else {\n status={fill:\"red\",shape:\"dot\",text:\"pass or cancel payload undefined\"};\n return [{payload:status},null,null];\n }\n}","outputs":3,"noerr":0,"initialize":"","finalize":"","libs":[],"x":196,"y":85,"wires":[[],[],[]],"info":"# OK/Cancel dialog helper function\n\n## description\n\nThis is a little helper to make OK/Cancel dialogs easy to implement inside a data stream\n\n## how it works\n\nIf a message arrives at the **imput** a message dialog box is triggered. The original Message is cloned into `msg.dialogHelperOrgMsg`. If the dialog sends `msg.payload` with the **passPayload** the original message is released on the second output.\n\n## envioment variables\n\n- **title**  ***optional** a string displayed on the title of the dialog\n- **message** message to be displayed\n- **passPayload** the `msg.payload` expected on the imput to release to original message."},{"id":"b2689755.7e7e48","type":"subflow:fd36bbc4.fe50d8","z":"9d52d40a.a63668","name":"pass message?","env":[{"name":"message","value":"Let the message pass?","type":"str"}],"x":726,"y":1955,"wires":[["84e70024.bd2e1"],["fb2a3c99.ecc46"]]},{"id":"84e70024.bd2e1","type":"ui_toast","z":"9d52d40a.a63668","position":"dialog","displayTime":"3","highlight":"","sendall":false,"outputs":1,"ok":"OK","cancel":"Cancel","raw":false,"topic":"","name":"OK / Cancel","x":954,"y":1904,"wires":[["b2689755.7e7e48"]]},{"id":"333e900c.2ef9a","type":"inject","z":"9d52d40a.a63668","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"test message","payload":"","payloadType":"date","x":484,"y":1955,"wires":[["b2689755.7e7e48"]]},{"id":"fb2a3c99.ecc46","type":"debug","z":"9d52d40a.a63668","name":"confirmed msg","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"true","targetType":"full","statusVal":"payload","statusType":"msg","x":964,"y":2006,"wires":[]}]

```

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/f/bf57d466f2e47602ad217e7f9ed81d603f649d7b.png)

---

<div class="post-metadata">

### Author: ![Henjoe](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/henjoe/32/52335_2.png) [@Henjoe](https://discourse.nodered.org/u/Henjoe)
#### Post date: [10 December 2021 00:14 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/9 "2021-12-10T00:14:22Z")

</div>

Thanks ! Christian!

Highly appreciated your effort in here! 🙂

Regards,  
Henjoe

---

<div class="post-metadata">

### Author: ![Henjoe](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/henjoe/32/52335_2.png) [@Henjoe](https://discourse.nodered.org/u/Henjoe)
#### Post date: [15 December 2021 04:47 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/10 "2021-12-15T04:47:44Z")

</div>

Hi @Christian-Me ,

do you have sample subflow on how to use this sub flow?  
[https://flows.nodered.org/flow/35d0480ce9151b2a722fa9d185a37825](https://flows.nodered.org/flow/35d0480ce9151b2a722fa9d185a37825)

I want to get in JSON format all the data on my table, so that I can use it to store my data into variables or etc.

Hoping for your guidance.

Regards,  
Henjoe

---

<div class="post-metadata">

### Author: ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)
#### Post date: [29 December 2021 04:48 UTC](https://discourse.nodered.org/t/ui-table-row-contextmenu-doesnt-work/54851/11 "2021-12-29T04:48:34Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
