Execute function from UI

2,169 views
Skip to first unread message

Csongor Varga

unread,
Dec 3, 2016, 4:02:59 PM12/3/16
to Node-RED
Hi All,

I am guessing this is some HTML5 foundation question. I have some database entries and I use the template node to format a HTML table from the entries and a UI template node to display. This is all good, thanks for the earlier help for that.

I want a hyperlink in that HTML for each line to process that entry. What is the process to call node red from the UI? I can create a HTTP request and response in node red and generate the HTML link to call that, but that would navigate the browser away from the UI. There must be a better solution for this. Is this what websockets are for? 

Regards,
Csongor

Walter Kraembring

unread,
Dec 4, 2016, 8:37:06 AM12/4/16
to Node-RED
 Is this what websockets are for? 

Well, yes, it is bi-directional so, yes. I am doing exactly that plus I use it to update the web page elements from the server

Julian Knight

unread,
Dec 4, 2016, 10:05:12 AM12/4/16
to Node-RED
If you are using Dashboard (AKA UI), any visual element that is linked to a msg variable and changed by a user will be sent back to NR, simply connect something downstream of the Dashboard template node to see that. Probably easier to use a button/switch though that than a link. With a link, you will probably have to intercept the link click in your front-end javascript in order to send some data back.

If you use a standard hyperlink, you will, of course, end up with a page refresh each time the user clicks.

Csongor Varga

unread,
Dec 4, 2016, 12:59:20 PM12/4/16
to Node-RED
Julian thanks for the hint. I should just have read the info a bit further. It seems it is already implemented but not with href:
Sending a message:
<md-button ng-click="send({payload: 'Hello World'})">
    Click me to send a hello world
</md-button>
Will display a button that when clicked will send a message with the payload 'Hello world'.

Colin Law

unread,
Dec 5, 2016, 3:31:51 AM12/5/16
to node...@googlegroups.com
Well you did ask for a hyperlink, not just a way to send messages back
to the flow from the UI.

Colin
> --
> http://nodered.org
>
> Join us on Slack to continue the conversation: http://nodered.org/slack
> ---
> You received this message because you are subscribed to the Google Groups
> "Node-RED" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to node-red+u...@googlegroups.com.
> To post to this group, send email to node...@googlegroups.com.
> Visit this group at https://groups.google.com/group/node-red.
> To view this discussion on the web, visit
> https://groups.google.com/d/msgid/node-red/deaaf47b-96e7-4084-bcad-f296d4bbf0dc%40googlegroups.com.
>
> For more options, visit https://groups.google.com/d/optout.

Csongor Varga

unread,
Dec 5, 2016, 3:46:29 AM12/5/16
to Node-RED
It did not occur to me that there might be other options as well. Btw, I included the above example to the template and nothing happens. This is the template which is rendering my table:
<table>
    <tr><th>Title</th><th>Torrent</th><th>Date</th><th>Remove</th></tr>
    {{#payload}}
        <tr class="">
            <td><a href="{{details}}" target="blank">{{title}}</a></td>
            <td><a href="{{link}}" target="blank">Torrent</a></td>
            <td>{{timestamp}}</td>
            <td><md-button ng-click="send({payload: {{id}} })">Remove</md-button></td>
        </tr>
    {{/payload}}
</table>

I am passing this to the UI template node. The text "Remove" is appearing, but it is not formatted as a button.

Did I get the concept wrong?

Regards,
Csongor

Csongor Varga

unread,
Dec 9, 2016, 3:50:51 AM12/9/16
to Node-RED
Hi Guys,

Anyone ever tried using the md-button on the template UI node? I followed the documentation on the Info tab, but it does not seem to be working.

Regards,
Csongor

Julian Knight

unread,
Dec 9, 2016, 6:10:50 AM12/9/16
to Node-RED
Yes, here is an example:

<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>

Peter Scargill

unread,
Dec 9, 2016, 7:22:47 AM12/9/16
to Node-RED
Julian your example of using a button in a template is GREAT - because you can do the one thing you can't do using the button as a normal button - i.e. change the background colour !!!

But one request if you have an idea how to do it. The great thing about buttons is they can be sized...   I note the button in your example is just one line high. Is there a way you know of to alter that code so that the button takes on the size of the outer template???

Why change button backgrounds?  RGB buttons of course.

Walter Kraembring

unread,
Dec 9, 2016, 7:56:56 AM12/9/16
to Node-RED
Why change button backgrounds?  RGB buttons of course.

ON/OFF buttons as well ;) 

Julian Knight

unread,
Dec 9, 2016, 8:18:03 PM12/9/16
to Node-RED
Peter, that example can be as high as you want - you could put an entire copy of the collected works of Shakespeare in there! Images too. :-)

Just include whatever HTML you want.

<md-button ng-click="send({payload: 'Hello World'})">

    Click me to send a hello world
    <div>Another paragraph of text</div>
   
<ul>
       
<li>How</li>
       
<li>About</li>
       
<li>A</li>
       
<li>List</li>
   
</ul>
</md-button>

Peter Scargill

unread,
Dec 10, 2016, 4:22:01 AM12/10/16
to Node-RED
Hah, yes indeed - I don't think the collected works would quite fit on my screen.  I was thinking more of having the button background fit the alloted space for the template - but when you said whatever HTML that triggered me to add 100% height class - and that worked exactly as expected... problem solved.

This just keeps getting better.

<style>
  .filled { height: 100%; }
</style>
<md-button class="filled" style="background-color:green"   ng-click="send({payload: 'Hello World'})"> 
    Click me 
</md-button> 

Peter Scargill

unread,
Dec 10, 2016, 4:43:50 AM12/10/16
to Node-RED
However, just as things were looking rosy.....

But then again... no, on examination, compared to a row of buttons, a row of templates with buttons inside have huge transparent borders both vertically and horizontally.

I'm thinking a little insider knowledge might be needed to reduce that gap to what you might expect between two buttons of similar size - and so I tried a DIV - same result - large clear borders.

So can anyone advice how to eliminate those borders so that a filled template takes on the same size as a button given the same settings (2*3 etc).

??

Julian Knight

unread,
Dec 10, 2016, 4:56:46 AM12/10/16
to Node-RED
Yup, the Dashboard template node is very powerful indeed. Just a little over complicated because of the use of Angular.

I'd love to have a go at creating an alternative using vue.js and I did start to have a go but the Dashboard nodes are too complex to easily unpick and I'd need to create something that instigates a websocket for each SPA. I've not had the time to really get my head around it yet. I'm thinking of something like the original example flow I created before UI existed that auto-magically linked any form fields via a websocket. Except using vue.js would let you do it with any element. Maybe I'll get some time to play this winter.


On Saturday, 10 December 2016 09:22:01 UTC, Peter Scargill wrote:

Julian Knight

unread,
Dec 10, 2016, 4:58:59 AM12/10/16
to Node-RED
You will need to examine the CSS that is being activated by checking your browsers dev console. I imagine that the embedded div is picking up something unexpected. 

You might also try putting "!important" on your CSS to try and get it to take preference and adding margin/padding of zero (or whatever).

Peter Scargill

unread,
Dec 10, 2016, 5:08:40 AM12/10/16
to Node-RED
I tried !important and even !listen to me will you.   All to no avail - but you are right - example the CSS - meanwhile if any insiders have any info??

Peter Scargill

unread,
Dec 10, 2016, 5:12:40 AM12/10/16
to Node-RED
Well, that went no-where - the simple tools in Chrome that I'm used to using will not drill down to the level of an individual template. Time to go on a debugging course...

Julian Knight

unread,
Dec 10, 2016, 7:41:03 AM12/10/16
to Node-RED
Do you want to share your template - I've no time just now - need to book the flights to Boston for next years holiday & get the Christmas tree up! But I'll try to take a look later.

You should have enough in the standard Chrome dev tools. Or try Firefox with the Firebug addin. You can get an Angular plugin for Chrome dev tools too.

Peter Scargill

unread,
Dec 10, 2016, 7:50:13 AM12/10/16
to Node-RED
Having the tools and knowing what to do with them - two different things.

Ok, take 3 buttons - size 2 by 2. On a typical phone they will sit side by side and will the entire width of the page with only a little space between them. Nice.

Now take 3 templates - same size -  with this in them..

<style>
  .filled { height: 100% !important; }
</style>
<md-button class="filled" style="background-color:red"   ng-click="send({payload: 'Hello World'})"> 
    Click<br/>me 
</md-button> 

See the problem - and this of course does not stop at buttons - it could be little graphs, images etc... the point being - if we're working on a standard grid with those buttons being the basis of sizes, anything you put inside a template is I assume going to have the same issue - I tried a simple DIV as well as a button - same result - utterly disproportionate padding around the edges. Fixing this would be a big plus for me as I can see ALL sorts of uses for templates especially now I know how to hide the menu and mouse pointer.

Julian Knight

unread,
Dec 10, 2016, 9:07:05 AM12/10/16
to Node-RED
So why 3 templates? You could put 3 buttons in one template? I assume you want them in different cards?

Peter Scargill

unread,
Dec 10, 2016, 9:28:32 AM12/10/16
to Node-RED
I did think of that - but of course we're not just talking about buttons - I tried a coloured DIV and the same thing happens - it isn't the button - but the containing template.. using seperate templates (once this spacing issue is hopefully resolved) would also mean ease of matching the gaps between say a template button or item and a real button.  So imagine 3 items in a row - a button - a template - and another button - right now the template is going to look like the odd man out. Even if I DID put 3 buttons in a template - the issue remains on the outer borders of the template - so that two rows of these would have awfully big gaps between them - and given the limited real estate of a mobile phone - that is not a good idea...

Julian Knight

unread,
Dec 10, 2016, 9:30:21 AM12/10/16
to Node-RED
This controls the size of the buttons and is what you are overriding with your style:

.nr-dashboard-theme-light .nr-dashboard-template .md-button {
    background
: #9EE3F9;
    color
: #fff;
    margin
: 0 6px;
    padding
: 0 12px;
    min
-height: 26px;
    min
-width: unset;
    line
-height: unset;
}


In the tools, go to the Elements tab. Click on the top-left icon to select an element by clicking on it. 
Select one of the buttons and look at the Styles tab in the right-hand column of the dev tools.

You can see that this style comes from app.min.css from UI 

But the thing adding the extra spacing comes from the cards styles:

.nr-dashboard-template {
    padding
: 8px 10px;
    overflow
-y: auto;
}

If you select the parent card for one of the buttons and then find the above style, you can unselect the padding element and you will see that the button becomes the same 
size as the card and loses the padding.

So changing your style definition in your templates to:

<style>
 
.filled { height: 100% !important; }

 
.nr-dashboard-template {
    padding
: 0px 0px;
 
}
</style>

Or whatever padding you might like, fixes the problem. In fact, you only need do that in a single one of the template nodes.

What I'm not sure about is whether that will impact any other elements on a page but it doesn't seem to.

On Saturday, 10 December 2016 14:07:05 UTC, Julian Knight wrote:

Peter Scargill

unread,
Dec 10, 2016, 9:50:51 AM12/10/16
to Node-RED
Thank you for that Julian - VERY nearly there - but not 100% - and yes before responding I checked adding BORDER 0px - made no difference - so the buttons in the template did INDEED expand... but STILL smaller than the real ones. Here's a clue -  a DIV put in place of the button DOES go to the same size as real buttons... so perhaps something in the button itself? I tried putting padding 0px 0px !important into the styling next to the colour of my button but it made no difference.

Any idea. Also - a button used in a template - does not give that visual feedback that a button on it's own gives. I'm sure there's away around that but thought I'd mention it.

Julian Knight

unread,
Dec 10, 2016, 10:54:50 AM12/10/16
to Node-RED
Haha, well I didn't want to do everything for you Peter! I did note that they are not quite the same size as the equivalent from the button node.

OK, I will take pity on you because there is something slightly odd about this.

If you select one of the cards containing a template node button and one containing a button node button, you will quickly see the difference in style when you check the button element.

The manually created button element also gets some style from the theming:

.nr-dashboard-theme-light .nr-dashboard-template .md-button {
    background
: #9EE3F9;
    color
: #fff;
    margin
: 0 6px;
    padding
: 0 12px;
    min
-height: 26px;
    min
-width: unset;
    line
-height: unset;
}

Now what is odd is that my previous style code doesn't actually work properly though I think it should. In fact you need to supply padding and margin settings BOTH in your "lilled" style and in .nr-dashboard-template otherwise it doesn't work. Not sure why.

<style>
 
.filled {
      height
: 100% !important;

      padding
: 0 !important;
      margin
: 0 !important;
 
}
 
.nr-dashboard-template {
      padding
: 0;
      margin
: 0;
 
}
</style>

Peter Scargill

unread,
Dec 10, 2016, 11:18:33 AM12/10/16
to Node-RED
Thank you for taking pity on me - I was sure I'd tried that but clearly not - your solution works. Thank you.

One more issue to do with swiping - but I'll make a new topic...

Pete.

Csongor Varga

unread,
Dec 11, 2016, 6:36:48 AM12/11/16
to Node-RED
Julian, hopefully the last question from me. How can I make this work from a template node? (regular template, not UI_template).

I am using the template node to format some database values, and I want to add a button for each line. Therefore I have added an md-button for each line in the template, and passing the result to the ui_template. But nothing is displayed in the UI. What do I need to put into the ui_template to make that happen?

Regards,
Csongor

Julian Knight

unread,
Dec 11, 2016, 10:59:12 AM12/11/16
to Node-RED
You'll need to share the code and some example data I'm afraid.

Csongor Varga

unread,
Dec 11, 2016, 12:00:13 PM12/11/16
to Node-RED
Find the example below: I put your example to a UI template node. It is working as expected. No issues there. Next I put your example code to a template node, and that feeds to the UI template. In this case nothing gets displayed. I press the inject node, but only the text gets rendered on the UI.

Is it not possible to use like this?

[{"id":"9179e8c.28c1418","type":"ui_template","z":"15e1f6a1.aeab19","group":"c494ec5.4d1e51","name":"Template node","order":0,"width":0,"height":0,"format":"<div>In the UI Template: {{msg.payload}}</div>\n\n\n \n\n  \n\n<md-button ng-click=\"send({payload: 'Hello World'})\"> \n\n    Click me to send a hello world \n\n</md-button> \n\n  \n\n<md-slider ng-model=\"msg.payload\" ng-change=\"send(msg)\"></md-slider> \n\n  \n\n<div flex layout=\"row\" layout-align=\"space-around center\"> \n\n    <md-button ng-repeat=\"b in buttons\" class=\"md-icon-button\" ng-click=\"click(b)\"> \n\n        <ng-md-icon icon=\"{{msg.payload[b.payload]?b.icon2:b.icon}}\" \n\n                    ng-style=\"{color: msg.payload[b.payload]?b.color2:b.color}\"></ng-md-icon> \n\n    </md-button> \n\n</div> \n\n  \n\n<script> \n\n    scope.buttons = [{ \n\n        icon: 'pause', color: 'black', \n\n        icon2: 'play_arrow', color2: 'red', \n\n        payload: 'play', \n\n    }, { \n\n        icon: 'alarm', color: 'black', \n\n        icon2: 'alarm', color2: 'red', \n\n        payload: 'alarm', \n\n    }]; \n\n    \n\n    scope.click = function(b) { \n\n        if (!this.msg) this.msg = {}; \n\n        if (!this.msg.payload) this.msg.payload = {}; \n\n        this.msg.payload[b.payload] = !this.msg.payload[b.payload]; \n\n        this.send(this.msg); \n\n    }.bind(scope); \n\n</script>","storeOutMessages":true,"fwdInMessages":true,"x":384,"y":349,"wires":[[]]},{"id":"18dd6570.1c216b","type":"ui_template","z":"15e1f6a1.aeab19","group":"c494ec5.4d1e51","name":"From template node","order":0,"width":0,"height":0,"format":"<div>From template node:</div>\n<div ng-bind-html=\"msg.payload\">{{msg.payload}}</div>","storeOutMessages":true,"fwdInMessages":true,"x":521,"y":419,"wires":[[]]},{"id":"8f756d01.07088","type":"template","z":"15e1f6a1.aeab19","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<div>{{msg.payload}}</div>\n\n\n \n\n  \n\n<md-button ng-click=\"send({payload: 'Hello World'})\"> \n\n    Click me to send a hello world \n\n</md-button> \n\n  \n\n<md-slider ng-model=\"msg.payload\" ng-change=\"send(msg)\"></md-slider> \n\n  \n\n<div flex layout=\"row\" layout-align=\"space-around center\"> \n\n    <md-button ng-repeat=\"b in buttons\" class=\"md-icon-button\" ng-click=\"click(b)\"> \n\n        <ng-md-icon icon=\"{{msg.payload[b.payload]?b.icon2:b.icon}}\" \n\n                    ng-style=\"{color: msg.payload[b.payload]?b.color2:b.color}\"></ng-md-icon> \n\n    </md-button> \n\n</div> \n\n  \n\n<script> \n\n    scope.buttons = [{ \n\n        icon: 'pause', color: 'black', \n\n        icon2: 'play_arrow', color2: 'red', \n\n        payload: 'play', \n\n    }, { \n\n        icon: 'alarm', color: 'black', \n\n        icon2: 'alarm', color2: 'red', \n\n        payload: 'alarm', \n\n    }]; \n\n    \n\n    scope.click = function(b) { \n\n        if (!this.msg) this.msg = {}; \n\n        if (!this.msg.payload) this.msg.payload = {}; \n\n        this.msg.payload[b.payload] = !this.msg.payload[b.payload]; \n\n        this.send(this.msg); \n\n    }.bind(scope); \n\n</script>","x":276,"y":429,"wires":[["18dd6570.1c216b"]]},{"id":"864de060.5bf2c","type":"inject","z":"15e1f6a1.aeab19","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":128,"y":434,"wires":[["8f756d01.07088"]]},{"id":"c494ec5.4d1e51","type":"ui_group","z":"","name":"Counter","tab":"156af96f.f8fd27","disp":true,"width":"6"},{"id":"156af96f.f8fd27","type":"ui_tab","z":"","name":"Home","icon":"home","order":"1"}]

Julian Knight

unread,
Dec 11, 2016, 2:34:24 PM12/11/16
to Node-RED
OK, that flow doesn't have an ordinary template node in it? Also the Dashboard template called "From template node" contains "<div ng-bind-html="msg.payload">{{msg.payload}}</div>" and you don't need both references to the payload, if the payload contains HTML, take out the bracketed reference and leave the div empty.

Csongor Varga

unread,
Dec 11, 2016, 3:28:48 PM12/11/16
to Node-RED
I have to ask a clarification at this point. I left out the bracketed reference, and all I see is "Click me to send a hello world" which is the caption of the button (I am using your example from this chain). So script and rest of the md-... is getting ignored.

Julian Knight

unread,
Dec 11, 2016, 6:21:55 PM12/11/16
to Node-RED
OK, I see what is happening now. The problem is that both the Node-RED template and the UI template use double brackets. You need to change the StartSymbol and endSymbol for Angular. I know how to do that for Angular in general but not in Dashboard.

Here is the code for doing generally in Angular. Putting this in a Node-RED template connected to HTTPout:

<!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>

Csongor Varga

unread,
Dec 13, 2016, 2:05:30 PM12/13/16
to Node-RED
Hi Julian,

Thanks for this. I am not saying I understand what is going on here, I need some more reading on this topic.

On a slightly different note (also related to the "Node-red scheduler in Dashboard" topic): is it possible to build a custom form in the UI template using mb-switch, mb-button, etc element, but instead of each of these elements sending a payload, have a button which sends out one payload with the state of all the elements in the form?

Dave C-J

unread,
Dec 13, 2016, 3:11:45 PM12/13/16
to node...@googlegroups.com
can the ui_form element not do what you need ?

Csongor Varga

unread,
Dec 13, 2016, 3:17:39 PM12/13/16
to Node-RED
Thanks for the hint. I did not actually looked into the various elements to be honest. It just did not occur to me. I need to see some examples of what it actually does.
Reply all
Reply to author
Forward
0 new messages