[Announce] node-red-contrib-ui-contextmenu

Hi folks,

The new node-red-contrib-ui-contextmenu node allows users to add a popup context menu to their Node-RED dasbhoard.

My partner in crime (@Steve-Mcl) and myself have developed this new node to be used in combination with our new node-red-contrib-ui-svg node;


[{"id":"5f5f6e0b.54bb8","type":"ui_svg_graphics","z":"60ad596.8120ba8","group":"73b3392.fb47dc8","order":5,"width":"14","height":"10","svgString":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:svg=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" style=\"cursor:move\" preserveAspectRatio=\"none\" x=\"0\" y=\"0\" viewBox=\"-0.14965985715389252 0 900.29931640625 710\" width=\"100%\" height=\"100%\">\n  <image width=\"889\" height=\"703\" id=\"background\" xlink:href=\"https://www.roomsketcher.com/wp-content/uploads/2016/10/1-Bedroom-Floor-Plans.jpg\" />\n  <text id=\"camera_living\" x=\"310\" y=\"45\" font-family=\"FontAwesome\" fill=\"blue\" stroke=\"black\" font-size=\"35\" text-anchor=\"middle\" alignment-baseline=\"middle\" stroke-width=\"1\">fa-video-camera</text>\n</svg>","clickableShapes":[{"targetId":"#camera_living","action":"click","payload":"light_kitchen","payloadType":"str","topic":"light_kitchen"}],"smilAnimations":[{"id":"myanimation","targetId":"pir_living","classValue":"","attributeName":"r","fromValue":"0","toValue":"40","trigger":null,"duration":"2","durationUnit":"s","repeatCount":"0","end":"restore","delay":"","delayUnit":"s","custom":""}],"bindings":[],"showCoordinates":false,"autoFormatAfterEdit":true,"outputField":"","editorUrl":"","directory":"/var/tmp","name":"","x":580,"y":100,"wires":[["81065ae8.2b4058"]]},{"id":"34ea123d.de242e","type":"debug","z":"60ad596.8120ba8","name":"Clicked menu item","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","x":1010,"y":100,"wires":[]},{"id":"81065ae8.2b4058","type":"ui_context_menu","z":"60ad596.8120ba8","group":"73b3392.fb47dc8","order":5,"width":0,"height":-1,"fontSize":16,"position":"msg","outputField":"payload","xCoordinate":50,"yCoordinate":50,"menu":"fixed","menuItems":[{"id":"STOP","icon":"fa-stop","label":"Stop playing","topic":"","payload":"stop","payloadType":"str","visible":true,"enabled":true},{"id":"PLAY","icon":"fa-play","label":"Second","topic":"","payload":"play","payloadType":"str","visible":true,"enabled":true},{"id":"PAUSE","icon":"fa-pause","label":"Pause","topic":"","payload":"pause","payloadType":"str","visible":true,"enabled":true}],"colors":"native","textColor":"#ff8040","backgroundColor":"#7ed669","borderColor":"#b1aa12","name":"","x":800,"y":100,"wires":[["34ea123d.de242e"]]},{"id":"73b3392.fb47dc8","type":"ui_group","z":"","name":"Floorplan test","tab":"c43fd9d7.de3b98","disp":true,"width":"14","collapse":false},{"id":"c43fd9d7.de3b98","type":"ui_tab","z":"","name":"SVG","icon":"dashboard"}]

This results in the next demo, where you can see that this node allowed us to display a context menu in a floorplan (e.g. to visually control your devices at home):

So your dashboard will look like this:


The node is currently not available on NPM yet, so you will have to install it directly from our Github page (see command at the top of our readme page).

We are looking forward for your 'constructive' feedback, and we hope you like both nodes!

Remark: if you have other nice use cases where this node could be used (apart from our SVG node), please let us know so we can add examples to our Github readme page!

Have fun with it!

Steve and Bart


Good post Bart. I'm reserving this one for some decent screen shots.

Update 1...

1 Like

Thanks Bart and Steve.

I didn't get the alpha version of the contextmenu working.
Going to play now with this beta version in combination with the svg node to see how it's all working.

1 Like

Fix 1.0.1 now on Github: for context menu items specified in the input message, no output message was send anymore...

1 Like

Version 1.0.2 is now available on Github, containing a auto-hide feature.
See the readme page for more information about this new functionality.


  • You can specify a time interval in the config screen:


  • When the mouse cursor leaves the context menu, a timer will start counting.

  • When the mouse cursor enters again the context menu, the timer will be reset.

  • When the mouse cursors is outside the context menu for the specified time interval, the context menu will be closed automatically.

  • A time interval 0 means that the auto-hide feature is disabled, so the context menu will stay open (until a menu item is clicked or until somewhere outside the context menu is clicked ...)

Short demo:



Steve (@Steve-Mcl) has implemented a series of changes (version 1.0.4), but he is rather occupied at the moment. The changes are mostly related to colors:

  • Fix hover not working for theme and custom
  • Fix if old dashboard installed (call to ui.getTheme() fails, so menu isn't displayed)
  • Calculate border and hover colors from others (custom and theme)
  • Default color choice changed to "native"
  • Fix menu item list not sizing up when colour choice changed
  • Changed "native" text to "default"
  • Renamed custom color label "Border" to "Hover"

Demo for built-in dark theme (menu1=custom, menu2=theme, menu2=native)


Demo for built-in light theme (menu1=custom, menu2=theme, menu2=native)



We have published our first version (1.0.4) on NPM :champagne: :partying_face:


Then users can start using it in combination with our node-red-contrib-ui-svg node.

@dceejay: would be nice if you could add our both UI nodes also to your collection of dashboard extra nodes https://flows.nodered.org/collection/590bc13ff3a5f005c7d2189bbb563976 . Thanks!

Have fun!!
Steve (@Steve-Mcl) & Bart


Hi Bart, Hi Steve,
thank you for this node, really useful!
I tried it on my current development and it it works great!

I quickly ran into one issue
The table send the coordinates on a right-click together with the row index of the selected row.
But the message issued after I selected a menu item missing all the properties of the incoming message

So my flow don`t know which line to delete (or update).

It would be great if your node only add the relevant properties to the incoming message instead creating a new one. (and if a property is not defined in the ui (like payload or topic) it should leave them unchanged)

And by the way, do you know a easy way to trigger your context menu on a right click on any other ui widgets?
My idea is to show extra information or trigger other events when i right click on a switch or value like last updated, or WiFi or Battery status of the device "behind" that sensor or actuator

That makes sense. Normally I do that, but never done it before in a UI node. Will need to have a look ...

No... Last week @hotnipi has been so kind to send the coordinates when his new node-red-contrib-ui-state-trail node is being clicked. But I assume this functionality needs to be added for each other widget separately in their source code?

This was something I think I mentioned in our private chat Bart (about approaching @dceejay about the possibility of baking click/ right click coordinates into base dashboard) but think this may have fallen off the radar?

As for the request to have access to original message, I propose we simply keep hold of the msg that "popped" up the menu & adding it in the click output msg as (for example) msg.sourceMsg or msg.originalMsg or similar.

That way, the user gets access to anything and everything in the original message as well as the intended payload.


Thank you! Don`t hurry I have so many other things on my ToDo ist.

I`m not an HTML expert. I thought there could be a way to globally catch click events and send the coordinates and the underlying angular widget ... But maybe not.

I don`t have a specific opinion on the name but to put the originalMsg in a separate property sounds like a clean solution that both messages do not interfere.

In case of ui-table it was an easy task thanks to a callback function (I think I mentioned a mechanism like this in the trail discussion)

rowContext = function(e, row){

Possibly. Perhaps some jQuery selector & on event could be injected by a UI template node but I'm unable to explorer that for you at this time.

Any takers fancy a challenge? @BartButenaers, any thoughts on how he would trigger a menu from dashboard item event?

@Steve-Mcl, no idea about that. And no time to dig into it ...

Hey @Steve-Mcl,
It looked a good idea at first sight, but did a quick test with the debugger. In the next code snippet the output message will be created, when a (context) menu item has been clicked:


So currently the output message only contains a msg.menuItem field. Since we are talking only about a single field, I would like to enrich the input message (if available) with that extra menuItem field.

Something like this:

var outputMsg = {};

if ($scope.msg) {
   outputMsg  = $scope.msg;

outputMsg.menuItem = menuItem;


Is that OK for you?

Sure. Go for it.

Question tho (as it's been quite some time since we wrote this), at this point (menu item click), does $scope.msg have the original msg on it?

Since we "watch" in AngularJs for changes of the "msg" scope variable, I assume it contains the last received message.
Not at my pc, but I also assume it will be undefined if the user doesn't use "msg based" context menus, but instead a fixed context menu...

Hi Chris (@Christian-Me),

Could you please check my fix, by installing it directly from Github:

npm install bartbutenaers/node-red-contrib-ui-contextmenu

The original input message is stored in the output message as a sourceMsg field:


@Steve-Mcl Seemed that at server side we did some postprocessing, by adding some more extra fields. Therefore I implemented your idea, to make sure we wouldn't override the original topic ...

1 Like

great! Works! Thank you very much!


Just for you to know the installation *over the old version" spit out two warnings:

npm WARN ws@7.2.1 requires a peer of bufferutil@^4.0.1 but none is installed. You must install peer dependencies yourself.
npm WARN ws@7.2.1 requires a peer of utf-8-validate@^5.0.2 but none is installed. You must install peer dependencies yourself.

+ node-red-contrib-ui-contextmenu@1.0.8
updated 11 packages in 12.895s