Question regarding sub flows

I have so far not used sub flows in my flows. However, I do have a node pattern repeated a couple of times that would qualify to become a sub flow. But the problem I found when evaluating is that when using the sub flow in the flow, node configurations made in the sub flow becomes common to all instances of the sub flow. That then disqualifies the attempt I made

Has it ever been discussed or thought of having individual node configurations for each instantiated sub flow? I mean using the sub flow as template as of today but once it is inserted into the flow & configured it would have it's own configuration data

Maybe such thing should then not be called sub flow, I don't know, just a thought

There are environment variables that you can expose to the UI of the subflow node, which in turn you can use within the subflow.

But if you say "node configurations", what do you mean exactly ?

Hello Bakman,
Excuse me if I have misunderstood things with sub flows since I just started looking into them. Let's assume the following simple example:

We have a simple switch node acting as an msg filter in the sub flow. I want to use this sub flow many times in my flow so I insert it in various places, replacing many other nodes.

Assume I want to allow passthrough of messages containing certain words. For each instance in the flow I would like to configure individually "what words" should be allowed. But if I configure "flowers" it will be valid for all instances.

Another example is a sub flow like the following with a number of big timers.
It would be nice to have a sub flow allowing individual configuration for each instance. I realize I can make a copy of sub flows to make them unique but then I think the whole idea gets lost. As I said, I don't know if sub flow is the right thing, maybe this is more a sub node or a super node

I think the subflow Properties feature should let you do what you want

As long as the fields are accessible (ie, not in an actual node-configuration), you can use variables in the fields of the node.

Try this flow

[{"id":"259d3c5.25e9644","type":"subflow","name":"Test Subflow","info":"","category":"","in":[{"x":68,"y":48,"wires":[{"id":"85a7863a.593238"}]}],"out":[{"x":356,"y":48,"wires":[{"id":"85a7863a.593238","port":0}]}],"env":[{"name":"input","type":"str","value":""}],"color":"#87A980"},{"id":"85a7863a.593238","type":"switch","z":"259d3c5.25e9644","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"${input}","vt":"str"}],"checkall":"true","repair":false,"outputs":1,"x":194,"y":48,"wires":[[]]},{"id":"d7eb8a6b.21ea3","type":"subflow:259d3c5.25e9644","z":"4a7dddef.4dd00c","name":"","env":[{"name":"input","value":"joep","type":"str"},{"name":"Input","value":"joep","type":"str"}],"x":492,"y":216,"wires":[["b585ca25.280e18"]]},{"id":"7877088.3bb8178","type":"inject","z":"4a7dddef.4dd00c","name":"","topic":"","payload":"joep","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":290,"y":192,"wires":[["d7eb8a6b.21ea3"]]},{"id":"b585ca25.280e18","type":"debug","z":"4a7dddef.4dd00c","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":696,"y":216,"wires":[]},{"id":"4685d593.31dffc","type":"inject","z":"4a7dddef.4dd00c","name":"","topic":"","payload":"jack","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":290,"y":240,"wires":[["d7eb8a6b.21ea3"]]}]

There is a little piece missing about using the actual environment variables.

Do you mean how to use an environment variable in the node configuration is missing?

1 Like

I just put this demo together to show your first use case. I do not know Big Timer well enough to show an example with it. The idea is that "subflow properties" are in some part of the documentation just referred to as "properties", but can be called the same way as env variables. See if you can understand what the flow below does, I'll see if I can meanwhile come up with a better example/explanation.

[{"id":"e249edfe.7bb55","type":"subflow","name":"\"flowers\"","info":"","category":"","in":[{"x":80,"y":60,"wires":[{"id":"6aefdda8.83be34"}]}],"out":[{"x":300,"y":60,"wires":[{"id":"6aefdda8.83be34","port":0}]}],"env":[{"name":"word_to_search","type":"str","value":"flowers","ui":{"label":{"en-US":"Word to search for"},"type":"input","opts":{"types":["str","num","env"]}}}],"color":"#DDAA99"},{"id":"6aefdda8.83be34","type":"switch","z":"e249edfe.7bb55","name":"","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"word_to_search","vt":"env"}],"checkall":"true","repair":false,"outputs":1,"x":190,"y":60,"wires":[[]]},{"id":"b59c2994.22aab8","type":"subflow:e249edfe.7bb55","z":"44c03005.3699e","name":"Search for \"flowers\"","env":[],"x":390,"y":180,"wires":[["186675a.e75978a"]]},{"id":"6f4dd941.1614a8","type":"subflow:e249edfe.7bb55","z":"44c03005.3699e","name":"Search for \"test\"","env":[{"name":"word_to_search","value":"test","type":"str"}],"x":380,"y":260,"wires":[["b388bd87.8368c8"]]},{"id":"186675a.e75978a","type":"debug","z":"44c03005.3699e","name":"Found flowers","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":640,"y":180,"wires":[]},{"id":"de6c6136.bedd98","type":"inject","z":"44c03005.3699e","name":"","topic":"","payload":"This is a test","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":180,"wires":[["b59c2994.22aab8","6f4dd941.1614a8"]]},{"id":"d84a38b0.5e4608","type":"inject","z":"44c03005.3699e","name":"","topic":"","payload":"I have flowers","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":150,"y":260,"wires":[["b59c2994.22aab8","6f4dd941.1614a8"]]},{"id":"ce49eb1.bb91d18","type":"inject","z":"44c03005.3699e","name":"","topic":"","payload":"I'm a test with flowers","payloadType":"str","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":120,"y":340,"wires":[["b59c2994.22aab8","6f4dd941.1614a8"]]},{"id":"b388bd87.8368c8","type":"debug","z":"44c03005.3699e","name":"Found test","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":630,"y":260,"wires":[]}]

Thank you all for showing interest & providing suggestions/solution ideas!!!

Well, to some extent providing configuration data via injected properties may partly work for some nodes but not for others. In addition, this would pass on extra duties to the main flow that currently does not send such properties to the nodes (since it's not needed, they are already configured). I strongly believe in using sub flows to simply and eventually make flows more efficient but then it should really simplify

Wouldn't it be simpler if you just could insert a sub flow into your flow, double-click on it and you would configure what is inside as unique data configuration for that specific instance? Instead of having to cover up with env variables and injecting properties?

I think having a "super node" would really simplify the overall thing in such cases

The properties are not injected at run time they are set in the configuration of the subflow.

Isn't that exactly what @afelix's example does? Double click the subflow instance and set the subflow properties. The inject nodes in the flow are sending the subflow the data to operate on, not the configuration.

Wouldn't it be simpler if you just could insert a sub flow into your flow, double-click on it and you would configure what is inside as unique data configuration for that specific instance? Instead of having to cover up with env variables and injecting properties?

This is exactly how it works.

@Colin that was it indeed, would have been nice if it was also linked in the subflow docs

Yes, it works for that specific node & example, but in general, if all configuration data for any node could be reached that way I believe it could eventually be a solution

Responding to myself, it will only work for those configuration data fields where it is possible to insert env variables. And in many cases that is not the case


Like I tried to explain, that is exactly the way it is. For some nodes that works easier, for others (contrib nodes specifically) it is harder. I do not know enough about big timer to know if that could be done, and will have to play with it first. If a node allows you to set the configuration either through properties on the message object (for example in the msg.payload), or through the $env option in a TypedInput kind of selection, such as the builtin Change and Switch nodes offer.

If you can manipulate their configuration through $env, go use that as it is the easiest. If you can through properties on the message object, add an additional function or change node before where you need it and have the property set in the subflow accessed that way.

Speaking in general, this is already possible. However, for core nodes it might be easier, but for contrib nodes you have to rely on whether or not the creator implemented a way to interact with the configuration. Either through an $env option, or through attributes. I do know that for my own node-red-contrib-html-entities node it is not possible to edit the configuration through the msg object yet, that's on the task list :slight_smile:
For other nodes, it will depend on if it was ever implemented or not.

Edit: I just looked at big timer, it appears it is not possible to set up its configuration through the message properties.

Edit 2: As for the practicalities of using function/change nodes to set up parts of the flow based on subflow properties, the docs for this are still a bit scattered. It is worth knowing that both environment variables set up in the Node-RED settings, as subflow properties are accessed the same way:
Env variables: (Same link as @Colin posted above)
Meaning that in functions, using the same example as above you can access them as env.get("word_to_search"). In JSONata, you can access it as $env("word_to_search"). When setting up a subflow instance inside that subflow, you can set it again using the $ option if you enable that on the other subflow template.

I think it will work for any node property that accepts a string. Use ${subflowpropertyname} and it should work.

Interesting, I will have to try that

Yes, maybe many possible work-arounds, still not really making things more easy/obvious/less complicated. I still would favor a super node type of feature

Will it? By default string values in nodes aren’t evaluated unless the developer explicitly asks for that to happen.

Any node property set to the string ${FOO} will be replaced by the value of the FOO env var.

1 Like

It seems this works for config fields where you can type in such strings but it does not work for fields where you have to select a property via drop-downs, use spin buttons or set check boxes

So to make this happen would require (all) node authors to make changes, and, honestly, it would anyway not make a flow configuration easier to make and maintain, fiddling around with env variables like that

No, my original idea is better, would not require node authors to change anything, would be dead easy to use & understand, minimize risks for errors and a no-brainer to maintain. But it would of course require parts of NR core to be changed or extended I suppose

So for the time being, I think I will stick to copy node clusters and duplicates in the flows