First own UI node


#1

Hi,
I´m trying to develop my first UI Node,
I want to generate something like this:

but nothing happened.

If I leave the if condition, it shows me the image.

grafik

So my question, how can I change the image depending on the payload?
and make it possible to send a new payload when clicking?


#2

does anyone have an idea?


#3

Hey @Georg25,

For your first question, you might have a look at another discussion. But in that case the server-side flow decides which image has to be showed...

Bart


#4

Hi Bart,

thanks for the tip.

module.exports = function(RED) {
	function checkConfig(node, conf) {
		if (!conf || !conf.hasOwnProperty("group")) {
			node.error(RED._("ui_pic.error.no-group"));
			return false;
		}
		return true;
	}
	var pic = null; 
	function HTML(config) {		
	// define HTML code
		(function(scope) {
			scope.$watch('msg',function(msg){
				if(msg) {
					pic= config.offPicture;
				}
			});
		})(scope);

		//var state = config.onvalue;
		//pic = config.onPicture;
		var html = String.raw`
		<div>
			<md-button ng-click="sendVal()" ng-model="msg.targetValue">
				<img  src="/${pic}"> 
			</md-button>
		</div>`
		return html;
	};

If I make it this way the following error message appears:


#5

Hi @Georg25,

The function(scope) { ... } Javascript code from your example will now be runned on the server-side (i.e. in your flow), since it is located inside the HTML function. Indeed that HTML function is used to determine which html/javascript code needs to be send to the client-side (i.e. to the dashboard in the browser). Since the AngularJs scope is not defined on the server, you will get that error...

So you need to tell Node-RED that your Javascript code needs to be runned in the client-side (not in the server-side!). Think you have to put your code inside the initController, as you can see in this discussion.

But on the client-side you don't have the config (since that is the data from the config screen of your node on the server-side flow), so you will have to get the offPicture from elsewhere e.g. from the msg.payload ....

Bart


#6

ok but that was not the plan. Is not there an easy way to get the payload? And make an if-case with it?


#7

Hmmm, it might be that I'm mistaken. Have not published yet a single dashboard node either...

In this discussion you can see that the scope stuff is inside the html raw string, where you have also your config data available. And then you can put your IF into your scope function...


#8

Hi,
the only thing missing from my UI Node is that reading the payload at the right place.
I need the payload here

function HTML(config) { 
		var pic = config.onPicture;
		var html = String.raw`
		<div> 
			<md-button ng-click="sendVal()" ng-model="msg.userTargetValue" style="background-color: ${config.bgcolor}"> 
				<img src="/${pic}" alt="Bild kann nicht angezeigt werden"> "${state}"
			</md-button>
		</div>`
		return html;
	};

but i only get the payload here

RED.nodes.createNode(this, config);
var done = null;
this.on('input',function(msg){
if(msg.payload ==="1"){
state = config.onPicture;
}
else{
state = config.offPicture;
}
node.send(state);
return state;
});

so my question how can i get the paylaod from the lower function to the upper one?


#9

sorry for the wrong formatting between the two parts of the code :sweat_smile:


#10

Hi, it is better that you edit your post ( via image ) , so it becomes more readable with two sections of code.

Perhaps Hiroyasu (@nisiyama) can give you some decent advise? I had a look at the reference ui_list node, but it is at the moment blurry in my mind how it works with the message transfer between backend and frontend ...


#11

Hi, sorry I didn't have enough time to follow messages on forums.
Could you try watching message and setting scope variable something like this?

    function HTML(config) {
        var html = String.raw`
<div>
  <div ng-if="flag">True</div>
  <div ng-if="!flag">False</div>
</div>
`;
... ui.addWidget({
        ...
               initController: function($scope, events) {
                    $scope.flag = true;
                    $scope.$watch('msg', function(msg) {
                        $scope.flag = !$scope.flag;
                    });
                }
        ...
    });
...

#12

@nisiyama

thanks for you help,

I have this built into my code, after the restart of node-RED it displayed "false", now I give a payload on it and it displayed "true". And I can not switch to "false" anymore.
Or did I test it wrong?


#13

Umm..., in my environment it it flips True/False when new message arrives.
I have placed sample widget at https://github.com/node-red-hitachi/ui_sample
Could you try this code?


#14

Hey Hiroyasu (@nisiyama),

Did a quick test and your sample UI node indeed seems to toggle fine:

widget_test

Thanks for assisting us with the widget API !
Bart