Flow variables troubles

I have some troubles by using the flow variable. In one case with a javascript that's ok i can have a return of the Flow variable, but on another use case, it doesn't work... this is my flow, the one with the debug message is ok, the one with the hmtl is KO (i want to write the result of the Flow variable in a Canvas context, around a rectangle). thanks if you can help ! tSee my flow in my 2nd message ^^

Hi @jlb

your flow only includes a single template node, so doesn't give us the full picture of what you're trying to do.

When you share flows, please first read this post to ensure you format them properly.

Sorry, here it is:

[{"id":"1aed4db1.318612","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"8165070c.f8bec8","type":"template","z":"1aed4db1.318612","name":"html","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n <head>\n  <meta charset=\"utf-8\"/>\n  \n  \n </head>\n <body onload=\"draw();\">\n   <canvas id=\"canvas\" width=\"500\" height=\"500\"></canvas>\n    <script>{{{payload.draw}}}</script>\n </body>\n</html>\n\n\n\n","output":"str","x":410,"y":200,"wires":[["e46f2202.f0adb"]]},{"id":"6460da00.6d5c68","type":"http in","z":"1aed4db1.318612","name":"","url":"/test","method":"get","upload":false,"swaggerDoc":"","x":60,"y":200,"wires":[["6d9dba5b.d5a514"]]},{"id":"e46f2202.f0adb","type":"http response","z":"1aed4db1.318612","name":"","statusCode":"","headers":{},"x":630,"y":200,"wires":[]},{"id":"94994060.2fe75","type":"debug","z":"1aed4db1.318612","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":500,"y":140,"wires":[]},{"id":"9a0d36a3.66cc08","type":"function","z":"1aed4db1.318612","name":"","func":"total=flow.get(\"test\");\nmsg.payload=total;\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":140,"wires":[["94994060.2fe75"]]},{"id":"d76ddfb4.1bee6","type":"inject","z":"1aed4db1.318612","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":80,"y":140,"wires":[["9a0d36a3.66cc08"]]},{"id":"946553b2.76d2f","type":"config","z":"1aed4db1.318612","name":"","properties":[{"p":"test","pt":"flow","to":"\"essai\"","tot":"str"}],"active":true,"x":90,"y":80,"wires":[]},{"id":"6d9dba5b.d5a514","type":"template","z":"1aed4db1.318612","name":"Draw","field":"payload.draw","fieldType":"msg","format":"javascript","syntax":"mustache","template":"    \n    function draw() {\n        var essai=flow.get(\"test\");\n        var canvas = document.getElementById(\"canvas\");\n        var ctx = canvas.getContext(\"2d\");\n       \n        ctx.fillStyle = 'red';\n        ctx.fillRect(10, 10, 50, 50);\n        ctx.fillText(essai,200,20);\n     }\n","output":"str","x":250,"y":200,"wires":[["8165070c.f8bec8"]]}]

Let me know if below flow works like you want. I will explain shortly (after lunch) what is does (and probably why yours is not working).

[{"id":"9684f032.bdc55","type":"tab","label":"Flow 2","disabled":false,"info":""},{"id":"995ddd55.ca5fe","type":"debug","z":"9684f032.bdc55","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":620,"y":160,"wires":[]},{"id":"ad7f4f2e.e6bc2","type":"function","z":"9684f032.bdc55","name":"","func":"total=flow.get(\"test\");\nmsg.payload=total;\nreturn msg;","outputs":1,"noerr":0,"x":430,"y":160,"wires":[["995ddd55.ca5fe"]]},{"id":"7509f282.e1eb8c","type":"inject","z":"9684f032.bdc55","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":200,"y":160,"wires":[["ad7f4f2e.e6bc2"]]},{"id":"ac78b881.15ea28","type":"inject","z":"9684f032.bdc55","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":280,"y":320,"wires":[["5d8619da.8cff38"]]},{"id":"5d8619da.8cff38","type":"change","z":"9684f032.bdc55","name":"","rules":[{"t":"set","p":"test","pt":"flow","to":"0","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":320,"wires":[[]]},{"id":"d54734a.4fe7fc8","type":"function","z":"9684f032.bdc55","name":"","func":"total=flow.get(\"test\");\nmsg.payload=total;\nreturn msg;","outputs":1,"noerr":0,"x":310,"y":240,"wires":[["ddd9c5d1.531648"]]},{"id":"dd19166e.776478","type":"template","z":"9684f032.bdc55","name":"html","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<!DOCTYPE html>\n<html>\n <head>\n  <meta charset=\"utf-8\"/>\n  \n  \n </head>\n <body onload=\"draw();\">\n   <canvas id=\"canvas\" width=\"500\" height=\"500\"></canvas>\n    <script>{{{draw}}}</script>\n </body>\n</html>\n\n\n\n","output":"str","x":610,"y":240,"wires":[["9bef3bd1.152248"]]},{"id":"aeae9c8e.97146","type":"http in","z":"9684f032.bdc55","name":"","url":"/test","method":"get","upload":false,"swaggerDoc":"","x":160,"y":240,"wires":[["d54734a.4fe7fc8"]]},{"id":"9bef3bd1.152248","type":"http response","z":"9684f032.bdc55","name":"","statusCode":"","headers":{},"x":830,"y":240,"wires":[]},{"id":"ddd9c5d1.531648","type":"template","z":"9684f032.bdc55","name":"Draw","field":"draw","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"    \n    function draw() {\n        var essai={{payload}}\n        var canvas = document.getElementById(\"canvas\");\n        var ctx = canvas.getContext(\"2d\");\n       \n        ctx.fillStyle = 'red';\n        ctx.fillRect(10, 10, 50, 50);\n        ctx.fillText(essai,200,20);\n     }\n","output":"str","x":450,"y":240,"wires":[["dd19166e.776478"]]}]

Thx !
I've tried it but even if the debug is returning a value, this one is not displayed ont the html page... as it should be with this draw template code:

    function draw() {
        var essai={{payload}}
        var canvas = document.getElementById("canvas");
        var ctx = canvas.getContext("2d");
       
        ctx.fillStyle = 'red';
        ctx.fillRect(10, 10, 50, 50);
        ctx.fillText(essai,200,20);
     }

the value of "essai" is not displayed...and the rectangle is not displayed too, it means that the script is stopping before that on a error ?

@jlb, you have to make sure that the flow variable flow.test will have a value assigned before you make the rest call to the endpoint /test. I added the auxiliary flow to initialize that variable. So first thing click on the inject node indicated.

test

it works with with this litlle example, thx !

I have to see how to make it ok in my more complex project... but this should help

1 Like

How it works. Your flow is running in Node-RED server. The JavaScript you developed, on the other end, runs on a remote browser. You want to pass data from the runtime (server) to the browser running your code, more specifically the value of a flow context variable. The function node will read the flow variable value. The next template node (Draw) will insert this value into your code as text.

I understand, thx. I manage to receive the value with essai={{payload}}; but if the msg is equal to an array as [100,200,300,400], it returns only the first value "100".. if i change it like: essai=[{{payload.1}},{{payload.2}}]; i've got the desired values "100,200". Is it possible to receive all the values of the array in one shot ?

Another question ^^: How can i store datas in a global variable from my mustache template ? (i'd like to store the x,y position of the drawing on order to use it in another template or node). It seems possible using: {{flow[store].name}} but in don't see how to use the "store" item. For example i tried {{flow[200,300].essai}} in order to store [100,200] on the flow variable "essai" but it doesn't seems to work...

Try: var essai=[{{payload}}];

Storing multiple values to a flow context requires below syntax inside a function node. There is nothing in mustache syntax that allows you to handle Node-RED context.

flow.set(["x", "y"] , [x,y])

or :

flow.set("x", x);
flow.set("y" , y);

but this will work for code running in the server.

Thanks again,

var essai=[{{payload}}] ;

works well !!

But regarding to the storing of a flow variable in a template, it is mentionned in the template node info that it should be possible to store value in the flow:

2019-10-14%2009_15_05-Node-RED

But i don't see how to use the "store" parameter" ?

If I'm reading this right you're asking how to store a value in flow or global inside a template?

I don't believe that is possible.

The screenshot you posted shows how to access flow and global and other flow/global "stores" (as in an alternate storage area) not how to store data.

Of need be, read the documentation on context storage for a better understanding of the store concept

1 Like

Thanks , Ok, i've got to find another solution

The magic word in the screenshot was "from" - image
The template can read from the context - it can't write to it.
The template is like an empty form that values can be plugged into. It doesn't change any of those values.

1 Like

One more question, I'd like to set a flow variable with an array of type : [value1, value2]. I get my values from other variables, this my code:

flow.set('tag_old', const_nb_old);
flow.set('tag_old', const_agv_old);

flow.set("tab_agv["+flow.get("agv_old")+"]", flow.get("tag_old"));

i know that the two values "tag_old" & "tag_old" are ok in the debug return (they are just numbers from 1 to 20), but when i get the result of

flow.get("tab_agv");

I've got a strange resul like:
2019-10-15%2009_30_54-Node-RED

I should have something like that: [1,18], [2,10], etc... maybe there is a problem with the syntax in the first part ?

flow.set("tab_agv["+flow.get("agv_old")+"]"

Where is the comma that separates then context name from the value

I don' t understand what you mean... ? And a error in my post: the result that i attempt is something like that:
tab_agv[0]=1, tab_agv[1]=2, etc... from the expression tab_agv[agv_old]=tag_old. How to make it with a flow.set syntax ? the complete one i use is:

flow.set("tab_agv["+flow.get("agv_old")+"]", flow.get("tag_old"));

Is this syntax correct ?

Ahhhh that’s one line! On my phone it was split to look like two.

finally it works with that syntax, it was only my output message that was wrong !
if i put:

msg.test =flow.get("tab_agv["+flow.get("agv_old")+"]");

I retrieve the good result !

Sorry...:sweat_smile:

doesn't the second flow.set over write the first since you are setting 'tag_old' in both? is this maybe a typo?