Dynamically create dashboard items

I'm redesigning my lighting control from scratch.

Previously each light belonged to a "zone" (e.g. bedroom) and each "zone" had a set of presets which were "hard-coded". Here's an example of what I mean by "hard-coded":

In v2 of my design, I'd like to make a dashboard that will allow me to:

  • create zones, assign light fixtures to zones, and create "scenes" or presets. (from dynamically populated listboxes, which I know is possible). This would allow assigning a light fixture to more than one zone, e.g. for open-plan spaces

  • store the current lighting status for a given zone into a "scene" for that zone

This way, scenes and zones would be arbitrary sets, used only to control, (not contain) devices.

The only missing piece of the jigsaw would be to somehow generate a Node-RED dashboard dynamically.

For example, one zone might have 5 light fittings, and 7 "scenes". So I'd like to show 7 buttons and 4 sliders. Similar to this:

I believe this is possible with the dashboard template node. Can someone help me get started with this node? Here's what I have so far, to dynamically generate x number of buttons depending on how many objects there are:

var value = "hello world";
// or overwrite value in your callback function ...
this.scope.action = function() { return value; }

var howmanybuttons = global.get("home.3f_bedroom.light.preset").length

for (var i=0;i < howmanybuttons;i++) {
<md-button ng-click="send({payload:action()})">
    Click me to send a hello world

I thought the above would display 5x buttons (given 5 preset objects that I have already created) however it just displays the one.

You will need to design a JavaScript Object to hold all the data in a way that makes it easy to process. you can then feed that into a Dashboard template and use ng-repeat to walk the object and create the interface.

I'm doing something similar for my new home dashboard based on an aggregation of data from heating and other sensors. But I am using uibuilder with VueJS and bootstrap-vue instead of Dashboard.

Here is some of the example code:

1 Like

I have now managed to generate a set of buttons from a JS object store in global context.

However I've encountered a strange (Angular?) display issue. The first button is rendered with a greater height than the others. It's easier to show you:

I've not included any additional CSS, or changed anything from the default NodeRED dashboard theme. Here's my dashboard template node:

<div layout="" layout-align="space-between">
<md-button style="display:inline-block" ng-repeat="(key, value) in msg.payload" ng-click="send({payload: value.number})">{{value.name}}</md-button>

Thanks in advance for any pointers

You can't interleave script and html like that. Something like this will work:

<md-button ng-click="send({payload:action()})" ng-repeat="item in global.get("home.3f_bedroom.light.preset")">
    Click me to send a hello world
1 Like

Hi can you please share your json or detailed code, im wondering how to iteratively create buttons as you mentioned above

Hi @moseslee1986, I think this has been answered in the post directly above from @Techplex and also in the code snippet in Post #3, namely:

<md-button style="display:inline-block" ng-repeat="(key, value) in msg.payload" ng-click="send({payload: value.number})">{{value.name}}</md-button>

The ng-repeat basically repeats the element for each key-value pair in msg.payload (or whatever else you want)

Does that answer your question?