How to get subflow's parent's flow variable value where the flow variable can change

I keep the power states of some lights in flow variables, for example:

flow.garageeavelights
flow.backyardfloowlight
flow.drivewayflood

And I have a number of switch nodes that use jsonata to see if the saved value differs from a target value, e.g.:

($number(payload.On) = 1 and $string($flowContext('drivewayflood')) = "off") or ($number(payload.On) = 0 and $string($flowContext('drivewayflood')) = "on")

If the states differ, the msg is passed on...

I decided I wanted to create a subflow that took the payload and took the value of one of the flow variables (that I provide as an an input environment variable), but I discovered that:

The environment variable input cannot be set with either:

  • a flow variable, e.g. flow.whatever
  • a jsonata expression, e.g. $string($flowContext('drivewayflood'))

So I thought I would just provide the flow variable name (e.g. drivewayflood) and then grab the parent flow's variable value from the subflow... but I cannot figure out how to do that.

I mean, I could add the flow variable's value to msg before the call to the subflow, but the purpose of having a subflow is to reduce the node clutter in the flow that's calling it. Using the subflow would also make it easier to read the flow (since the jsonata in the switch node is hard to read). So if I can't just pass my current p[ayload to one subflow node without needing extra nodes, I might as well just keep my current switch nodes with the long jsonata expression...

So, how can I pass a payload and a selected flow variable to a subflow?

If you want to access a flow context variable from inside a subflow, use $parent.drivewayflood

That's not exactly what I want to do. I want the subflow to not know what the variable is a priori. So I want to either supply "drivewayflood" in a variable to the subflow, or simply provide the value of flow.driveway flood to the sub flow's environment variable input.

I.e. How do I retrieve the parent's flow variable value where I have the name of that variable inside a variable.

Because I don't see a way to provide the value of the flow variable to the subflow's environment variable input either via flow. or jsonata.

Hi ,

Not 100% clear on your query.
If your query is to set subflow env variable based on msg - that cannot be done.

If your query is on How to dynamically get object based on attribute name in a variable , you can do the same in function node.

msg.test = "abc";
env.get(msg.test) - should return the value of env variable abc.

This obviously assumes abc is defined else "undefined" will be returned.

Not 100% clear on your query.
If your query is to set subflow env variable based on msg - that cannot be done.

Based on flow, but yeah, I noted that wasn't possible.

If your query is on How to dynamically get object based on attribute name in a variable , you can do the same in function node.

msg.test = "abc";
env.get(msg.test) - should return the value of env variable abc.

Yes, I can do that, but to extend your example, "abc" is the name of the parent's flow variable and I want to retrieve the value of that variable. In pseudo-code, I would imagine it like this:

env.set("test", "abc");
var parentFlowVarName = env.get("test")
var parentFlowVarValue = $parent[parentFlowVarName]

This obviously assumes abc is defined else "undefined" will be returned.

I define the string "abc" in the subflow's node's environment variable input like this:

image

so in this example, the pseudo-code would be:

var parentFlowVarName = env.get("prev_flow_var")
var parentFlowVarValue = $parent[parentFlowVarName]

I'm just trying to accomplish everything in the subflow so that all I need in the parent flow is a bunch of copies of the subflow and simply set the name of the flow variable I want it to work with.

Like I said, I can accomplish this by adding an extra change node in the parent flow, but that defeats the purpose of my creating the subflow, my goals of which are:

  • Reduce the number of nodes in the parent flow
  • Reduce the redundancy I have currently using switch nodes & jsonata
  • Make the nodes in the parent flow easier to read (because the switch node's output label when using jsonata doesn't show the flow variable it's working on)

I fully expect this simply isn't possible, but I'm just asking you guys to be sure.

[quote="hepcat72, post:6, topic:58655"]

msg.test = "abc";
var parentFlowVarName = env.get(msg.test)
var parentFlowVarValue = $parent[parentFlowVarName]

I started a response in lines of above ... cos i think i eventually understood your ask.... when your response came. This i assume doesnt work else you wouldnt have been wrtiing this.

Did you try

var tempParent = $parent
var parentFlowVarValue = tempParent[parentFlowVarName]

Just a wild guess. Dont know if it will work. Sorry.

I will try it! Looks promising.

My test function node:

var prnt = $parent;
var pfv = env.get("prev_flow_var");
var pfv_val = prnt[pfv];
msg.prevState = pfv_val;
return msg;

produces an error:

"ReferenceError: $parent is not defined (line 1, col 12)"

My test parent flow sets this:

image

And then triggers the subflow node like:

image

No other ideas mate. Can only think that when we $parent.xyz is written ... .internal parser translates it into
$parent = parent flow context
And then runs a get() on it.... i.e $parent is not an object accessible to to child flow as a normal object.

Is your variable in parent's flow context ?
If so .... maybe

prnt.get(pfv) .... try it just in case.

This is the only thing i can think - which again i have not tried.

prnt is never set.

So yeah, I doubt this is possible.

I'm kinda behind in my version of node red. Perhaps there's an alternate strategy to my switch nodes like this one:

[{"id":"8ddb3938.81a45","type":"switch","z":"4c133ec2.a92a1","name":"differs","property":"payload","propertyType":"msg","rules":[{"t":"jsonata_exp","v":"($number(payload.On) = 1 and $string($flowContext('backyardflood')) = \"off\") or ($number(payload.On) = 0 and $string($flowContext('backyardflood')) = \"on\")","vt":"jsonata"}],"checkall":"true","repair":false,"outputs":1,"x":750,"y":2860,"wires":[["daf4b293.e7119","915e8d6c.89b0d8"]]}]

They meet the reduced number of nodes goal, but there's redundant jsonata code in all those nodes and it's difficult to see what flow variable is in them without double-clicking the code and awkwardly selecting the text to make it "scroll" sideways.

Does a newer version of node red let you set labels for the outputs on the switch nodes when there's jasonata?

Or... thinking out of the box... can I call a subflow from within a function node?

Here is the code you want:

var parentFlowVarName = env.get("prev_flow_var")
var parentFlowVarValue = flow.get("$parent."+parentFlowVarName)

Ah! Perfect. It works. You know, I had tried the jsonata version of this in a switch in the subflow, but couldn't figure it out. Not sure why it didn't occur to me to try this in the function node.

Thanks so much!

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.