Node-RED Dashboard Template Examples (AngularJS)
Published:
| by Julian Knight Reading time ~3 min.
📖 Kb
| 📎
Development
| 🔖
Node-RED
Some examples of using AngularJS with the Node-RED Dashboard. Not all features of Angular are accessible via the Dashboard.
Accessing the msg object 🔗︎
When using Dashboard, the Node-RED server (the back end) sends data via Socket.IO to the client browser (the front end). This comes in the form of a msg
object. in similar form to the msg that flows through the rest of Node-RED.
To access the msg
object from within a client Angular script. Put this into a Dashboard Template node:
<div ng-bind-html="msg.payload"></div>
<script>
//console.dir(scope) // this also works
//console.dir(scope.msg) // This doesn't because scope.msg doesn't yet exist
// Lambda function to access the Angular Scope
;(function(scope) {
//console.log('--- SCOPE ---')
//console.dir(scope) // this works but you only get it once (on startup)
//console.dir(scope.msg) // Doesn't work for because scope.msg doesn't yet exist
//Have to use $watch so we pick up new, incoming msg's
scope.$watch('msg.payload', function(newVal, oldVal) {
console.log('- Scope.msg -')
console.dir(scope.msg)
})
})(scope)
</script>
A couple of ways to send a msg back to Node-RED 🔗︎
This shows you how to set up some buttons and a slider widget that send data back to Node-RED. As always, add this code to a Dashboard Template node.
<div>{{msg.payload}}</div>
<md-button ng-click="send({payload: 'Hello World'})">
Click me to send a hello world
</md-button>
<md-slider ng-model="msg.payload" ng-change="send(msg)"></md-slider>
<div flex layout="row" layout-align="space-around center">
<md-button ng-repeat="b in buttons" class="md-icon-button" ng-click="click(b)">
<ng-md-icon icon="{{msg.payload[b.payload]?b.icon2:b.icon}}"
ng-style="{color: msg.payload[b.payload]?b.color2:b.color}"></ng-md-icon>
</md-button>
</div>
<script>
scope.buttons = [{
icon: 'pause', color: 'black',
icon2: 'play_arrow', color2: 'red',
payload: 'play',
}, {
icon: 'alarm', color: 'black',
icon2: 'alarm', color2: 'red',
payload: 'alarm',
}];
scope.click = function(b) {
if (!this.msg) this.msg = {};
if (!this.msg.payload) this.msg.payload = {};
this.msg.payload[b.payload] = !this.msg.payload[b.payload];
this.send(this.msg);
}.bind(scope);
</script>
Ways to update the UI 🔗︎
Using Anglular and a Dashboard Template, we can update the UI direct from an incoming msg, by doing a calculation after receiving a message or by calling a function.
<h1>Msg Topic: {{msg.topic}}</h1>
<h2>msg.payload.a</h2>
<div ng-bind-html="msg.payload.a"></div>
<h2>Calculated after receiving a msg</h2>
<div>{{myCalc}}</div>
<h2>Call a function on click</h2>
<div ng-click="click(b)">Click me to change the number</div>
<div>{{myNum}}</div>
<script>
// Lambda function to access the Angular Scope
;(function(scope) {
//Have to use $watch so we pick up new, incoming msg's
scope.$watch('msg.payload', function(newVal, oldVal) {
console.log('- Scope.msg -')
console.dir(scope.msg)
scope.myCalc = scope.msg.payload.b * 2
})
// Function triggered by clicking on a div
scope.click = function(b) {
if ( ! scope.myNum ) scope.myNum = 0
scope.myNum++
}
})(scope)
</script>
Date Picker Example 🔗︎
<div>
<md-datepicker ng-model="myDate" md-placeholder="Enter date" ng-change="send({payload: myDate})"></md-datepicker>
</div>
Dynamically inject HTML 🔗︎
Use this code in a Dashboard Template to render a msg.payload containing HMTL.
<div ng-bind-html="msg.payload"></div>
Use an input array or object to create a list 🔗︎
Angular has an ng-repeat
property that lets us walk through an array (or object) to dynamically create a list, table, etc.
<div ng-repeat="(key, value) in myObj"> ... </div>
Use a tracking ID if possible as this helps Angular know when something needs updating:
<div ng-repeat="(key, value) in myObj track by myObj.id"> ... </div>
You can also use ng-repeat-start
and ng-repeat-end
elements to wrap content.
See the Angular v1 docs for ngRepeat for more details.
Working example, use this in a Dashboard Template node:
<table>
<tr ng-repeat="(key, value) in msg.payload">
<td>{{key}}</td>
<td>{{value}}</td>
</tr>
</table>
Change the Angular delimiters 🔗︎
If you want to send data through a Node-RED Template node before sending it to a Dashboard Template node, you will find that, since both use the same delimiters (double curly brackets). So you need to change the delimiters in the Dashboard Template.
<!DOCTYPE html>
<html ng-app="ngApp">
<head></head>
<body ng-controller="ngCtrl">
<h1>Topic: {[{topic}]}</h1>
<pre>
{[{payload | json }]}
</pre>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.12/angular.min.js"></script>
<script>
var ngApp = angular.module('ngApp', []);
ngApp.config(function($interpolateProvider) {
$interpolateProvider.startSymbol('{[{');
$interpolateProvider.endSymbol('}]}');
});
ngApp.controller('ngCtrl', ['$scope', function($scope) {
// Need to wrap with TRY in case not valid JSON
$scope.payload = JSON.parse(decodeEntities('{{payload}}'));
$scope.topic = '{{topic}}';
}]);
function decodeEntities(encodedString) {
var textArea = document.createElement('textarea');
textArea.innerHTML = encodedString;
return textArea.value;
}
</script>
</body>
</html>