Ok, subflows - again - confused about looking at their nodes

I have another problem with a subflow and and am trying to work it out myself.

But the subflow isn't playing fair.

I have delay and trigger nodes in it but when I look at it they aren't showing themselves being used.

So I take it that the subflow viewing is only that and it is not real time.

I think I just answered my own question, but I want to check.

I dug up some notes I took:

If you are on 0.20, then the nodes in the subflow can access the parent flow context. If you have a flow context variable called foo then the nodes in a subflow can use $parent.foo to access it.

Ok, nice and probably understandable when I wrote it.
Not any more.

I am using both the change node and stuff in a function node.

I've tried searching for how to access flow.context and subflow but to little benefit.

I am using NR 1.3.5.

I'm guessing (note: GUESSING!) that in the function node I would do something like:

var j = flow.get("$name")

and it would get it from the parent /calling flow?
But it is not clear to me.

And if that does work, how does it translate when I use the change node?

Yeah, I'm not getting it. maybe I need to put more work into learning it, but all I seem to get is blood on the brick wall upon which I am hitting my head.

Ok, what I have since learned:

In a flow, you access it's flow.context by:

var x = flow.get("name);

Which is fair enough.

If you want to put it in a subflow you have to make it this:

var x = flow.get("$parent.name");

Which - again - is kind of ok.

But it makes it b!00d% hard to create code, select all the nodes and put them into a subflow if any nodes use flow.context.

You have to go in and edit any/all instances and precede any context use with $parent.

That's a few hours of painful learning I just went through.

But I am not sure that is the RIGHT way to do it.

I can't find a documented way to do it. This was determined by the throw enough stuff and eventually it will stick.

I don't think that is a good way to learn. Maybe I will be more inclined to remember it, but: wow, was it painful!

Oh, can someone confirm this and what is the go for GLOBAL context?

Same?
$parent. or $global? Again: I haven't been able to find good documentation.

Andrew, using flow and global context inside a subflow is (imo) asking for trouble. A subflow should ideally be free from side effects. (Aka pure).

It's quite hard to explain in a quick reply but there are many articles on the internet on "pure functions"

In simple terms, when you move parts of your flow to a subflow, to access external values (like flow context) you should pass in (via the msg) any values needed & pass out the result.

2 Likes

To access global context, you use the global object instead of the flow object.

So in a function node you do global.get("foo") or in a change node, you'd select the "global" type on the left of each input.

1 Like

But.... and please understand I am seemingly not understanding it.

in the subflow I have to flow.get("$parent.name")

Reading your reply accessing global variables is different to flow ones in two ways.
1 - glabal rather than flow
2 - no $parent

Correct?

Yes Steve, I kind of get that.

But when I do a search on node red access flow variable in function I get sent to sites like this:

context

Na, not helpful.

Then

Sounds familiar

Not helpful.

Where is the magic stuff explaining how to use the $parent part?

That is what was driving me crazy.

However, in retrospect: Yeah, I shall have to re-write the subflow and code around it to send the stuff I want into the subflow in the message.

Anyway, back to bashing my head against the wall.

And further: Stupid me...

After even more digging seems I had already set up the message to have those values hidden (not on purpose) in there.

I just got lost with the message complexity carrying all this weather stuff.

I may have got this part now working.

But I am still not sure about what the factual syntax is for accessing context from flow or global from within a subflow.

Sorry but one of those links I posted
Sounds familiar

Shows the wrong (or very outdated) syntax on how to get access to the flow variables.

Or, again: am I wrong.

I get that documents change over time as things get better.
But it doesn't help me when I read how to do it from an earlier version and doesn't work on the current version.

Can you clarify this part - please?

Subflow Instance properties
Since 0.20, Subflows can be configured with instance properties. These appear as environment variables within the Subflow and can be customised for individual instances of the subflow.

Though I have probably got even this wrong in how I am reading it. :sob:

You have linked to docs about environment variables that are accessed via the env object. That is unrelated to context which is accessed via the flow and global objects.

1 Like

As I said: I was confused with the terms.

I found it when I was searching for how to access flow context from within a subflow.

Could you please show me where this is so I can book mark it and read it - and make my own notes for future use?
My searches yield misdirecting things which aren't helpful to me.
Thanks.

This is your starting point - Working with context : Node-RED

It describes the three scopes of context (node-level, flow and global).

It also has a big yellow info box explaining how nodes inside a subflow can access the parent flow context.

2 Likes

Just asking...

This line:

Note : for nodes in a subflow, the flow context is shared by those nodes and not the flow the subflow is on.

Is it helping any one now?

As NR is way beyond 0.20 - to which the next sentence refers... Wouldn't it help people like me by removing it.

It is out dated. Isn't it?

Everything in that text is accurate and correct for the latest version of Node-RED.

The text says " From Node-RED 0.20," - which means this is a feature that was first added in 0.20 and everything since.

Yes, but the bit before that is no longer correct if I read that correct.

I'm still confused. But that's my problem. Ok.

Note : for nodes in a subflow, the flow context is shared by those nodes and not the flow the subflow is on.

That is a correct statement of fact. For nodes inside a subflow, their flow context is shared amongst themselves and is not the parent flow context.

The next sentence then explains that from Node-RED 0.20 it is possible for a node inside a subflow to access the parent flow context. Before Node-RED 0.20 it was not possible for a node inside a subflow to do that.

@Trying_to_learn perhaps all may become clearer to everyone if you can tell us what you are trying to achieve. What is your end goal?

To me that is clearer than what is written:

the flow context is shared by those nodes and not the flow the subflow is on.

Hey Paul.

Alas it is not a simple thing.

This started with me playing with a subflow and weather.

I have a lot of code/nodes to create a message which determines the icon to show.
It was working but I was/am a long way from completing it fully.
Though I hope to never have to include tsunami as an icon to be shown.

But things like fog, snow, hail and maybe a couple of others weren't applicable and so they were never implemented.
Then snow snuck up on me.
The external code indicated the subflow didn't find the correct icon.

(That's a whole other story)

Anyway, somehow it started to work.
But in my fixing that, other problems suddenly started to happen. How? Why? Dunno. :man_shrugging:

So I got bogged down in looking at the subflow while sending real data into it. I since have deduced that a tab with a subflow's contents is NOT dynamic and so can't be watched in real time.

So I had to take all the subflow back out of there and put it in the main tab. (Oh the fun finding the space)

But I then had to change all the parent flow context access back to this level.
That is about when I realised there is a problem with how I was doing that.

I simply had flow.get($name) rather than flow.get("$parent.name")
But in finding that out, it opened a can of worms between what I had noted on how to do it and what is now documented.

Yes, my fault for not keeping up with the new docs.

I then got all the parent flow context stuff worked out. All was good - I hoped.
But then something else popped up and so I started this thread - from memory.

I was told to not use context from the parent flow in subflows.
And after a bit of sitting and thinking (well: a lot) I decided to take that on and send the message into the subflow to completely get around the problem.
Done.

But I was wanting to get definitive confirmation of the syntax so I can update my notes.

SO....???? What now?

So now, most of the problem is gone, but it kind of has raised another question which is/was teetering on being asked:

If it is bad programming to access context from the parent flow: why is it supported?
To me if the first statement is true, allowing context access to/of the parent flow is only promoting bad programming practice.

It's a similar situation as globals in any language, It is possible but not advisable.

An easy way to tell if you've written a good function or class etc, is if you can reuse it in another application without modification. So by accessing outside variables (parent flow context or globals) you immediately have an external requirement for the "thing" to work. Another good test is if the function/subflow always returns the same value for the same known inputs (i.e. has no side effects / doesn't rely on external values that might have changed)

Without studying the various disciplines, it is difficult to grasp why this matters & it is quite difficult to explain fully why but trust that there is good reason these disciplines exist.

If you are interested in reading more, look into the DRY and PURE principles to start with.