Add "context" to types provided in Typed Input

The Typed Input widget already supports flow and global as types but it doesn't support "context". It would be really helpful if this was added so that a custom node could offer a complete selection of store types in a standard way. Currently, you have to do this manually.

Only discovered this was missing as I am trying to add an improvement to uibuilder's cache node. Up till now, the cache has only used context and manually builds a list of store types. Now I want to allow context, flow or global and to use the Typed Input since this is a much nicer compound input box for people to use.

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

I never got a response on this. It would be very helpful to get one.

I came across this recently myself - initially I built a select list and populated it manually in oneditprepare with some code stolen from the typed input source, but it was kludgy.

   var contextStores = RED.settings.context.stores;

     if (contextStores.length > 1) {
       $("#node-input-storage").prop("disabled", false);

       contextStores.forEach( (store) => {
         $("#node-input-storage").append(`<option value="${store}">${store}</option>`);
       })
     }

I ended up going back to just accepting a flow or global input and require the user to enter names for each of the properties my node wants to store in context. I would prefer to have the user provide a unique base name and a context store and then my node could make the references that it needs, but managing that manually didn't feel on paradigm.

I'm still not sure why there is no response on this. Seems like a simple enough change and a reasonable enhancement.

I could try and take a crack at it. I haven't made any pull requests on the core before, but I've been poking around context storage and the typed input source a lot recently.

You could implement it so that RED.util.evaluatenodeproperty returns an object with a Get/Set function scoped to the context from the typed input. You would just need to be sure that existing nodes couldn't accidentally get context through the default typed input if they aren't expecting it.

1 Like

I remember reading this thread and remember wondering what use it could be. I am still struggling to understand the use case.

So flow and global variables are externally exposed but the context variable isn't. It cannot accidentally or deliberately be changed. There are plenty of times that it would be useful to have an input msg set a value that a later message can compare to, we use that a lot in flows, but we are forced to use flow/global variables unless we use a function node - that seems off for a supposed low-code tool right?

So having context as one of the options along side flow and global means that you can store/recover within a change node.

Indeed, then any custom node could also use this. Take some of the uibuilder nodes for example. Several of them now make internal use of variables - HOWEVER - in order to use an internal context variable, I have to hand code support into the node. But I shouldn't need to do that. If the typed input widget supported context variables as well as flow/global, I could simply offer a standard typed input widget instead of having to craft my own.

The above demonstrates this, it is a uibuilder cache node. The cached data is stored by default in the node's context store but you can choose a flow or global if you prefer. You can also choose between various store types if you have them defined. But it is pretty crazy that I have to hand code this when a typed input field should be able to do the job.

It should be trivial to achieve this since the context type is as easy to access in custom code as flow or global and it would simply be another entry in the possible list:

image

To recap then, I've outlined two common possible uses:

  1. A comparator - an earlier msg stores the previous value and a later msg can compare with it. Or it could be two different input flows - lets say light levels from 2 different sensors that update at different times and a change node averages the 2 values whenever either is received. Currently that either forces the use of flow or global (which really isn't needed) or requires a function node.
  2. A custom node offering a protected store updated by an incoming msg property. Which currently requires again the forced use of flow/global if you want to use typed input, or the forced use of custom input otherwise.

Hope that makes things a little clearer?

I took a really fast pass at implementing this here - not at a level that I would create a PR yet, but @TotallyInformation if you wanted to clone the repo and see if it does what you want, I would consider putting more time into it. I wasn't sure if you were looking for just the store or a store and flow/global type, so I just did the store for now.

I also implemented a corresponding RED.util.evaluateNodeProperty which returns an object which has a flow.set/get and global.set/get which already have the store built in.

Example code from my test node:

        node.storage = config.storage;
        node.storageType = config.storageType;

        node.store = RED.util.evaluateNodeProperty(node.storage, node.storageType, node);

        node.store.global.set("testGlobal", "Hello");
        node.store.flow.set("testFlow", "World");

        console.log(node.store.global.get("testGlobal"));
        console.log(node.store.flow.get("testFlow"));

image

I feel like I am missing the bigger picture somewhat Julian (I am fresh back from a vacation so it may be that I am still in 1st gear)

So assuming an option for local context is added, would you expect the user to be able to specify a context variable name? This is the confusion I have - in that - what benefit does that bring to an end user?

Also, since other nodes have no access to another nodes context, why not simply use internal variables. (though TBH, I understand there could be viable benefits of being able to use persistent context in this case - especially on cloud based systems where file storage is not necessarily a "given")

Apologies if I am missing something obvious.

Well, why not? It is consistent with the flow/global use and a node like the change node could certainly make use of multiple context variables - though admittedly this would be a fairly unlikely need - however, it would be consistent and since the framework is already in place within typed input, I don't see why you wouldn't want to do that, it doesn't hurt anything after all.

In the uibuilder nodes, I've grey'd out the name for context because there is only ever 1 variable in use, but that wouldn't necessarily be true for other node types.

And how would you do that with a change node? And what about what I said about having a choice? My nodes give a choice to use context - which can't be externally changed - or flow/global which could be externally changed if you wanted to. The first is safer but less flexible, the second requires more care but gives other possibilities for processing.

Why are we forcing people who want/need that choice to hand-craft something which is a fair bit of work to get right when you already have a tool that does 60% of the job and where adding the remaining option would make that tool more consistent?

And then yes, there is also the multiple store issue. I've had to hand-craft that as well, a lot of custom code that is simply a duplicate of what mostly already exists and probably deals with edge cases I've not thought about.

AND, I'll come back to the really obvious use-case - CHANGE NODE - The ability for the change node to use a context variable that cannot be externally changed and is therefore safer but still has the flexibility of naming and store type - WHY NOT? I can think of many flows where I've set a flow/global variable that would have been much better served with a context one.

It should be exactly the same as the flow and global options to be honest. For the reasons outlined above. While sometimes only a single var might be needed, nodes with more options like the change node could make use of more. And yes, the storage type is certainly needed so that persistence is available. Making it the same look and feel as the flow and global options is consistent and less jarring for users as well.

Julian, I am not against this and will happily support it if it is the right thing to do.

Regarding your CHANGE NODE example.

Suppose for 1 second, core was updated and you could now chose context as a "thing" in the typedInput. Could you provide a meaningful example of use? I am really struggling to see what you see. Its not like the user can use a switch or other node to access or update this context value. The only benefit I see are compound rules and even then, you could work on the msg object (aka PURE)

Please show me :slight_smile:

Somewhat contrived but:

The sensors return values - lets say the temperatures from the top and bottom of a water tank. I want to act on the average of those.

I've used a flow variable there but I don't really want to because (a) It messes up my list of flow variables which might be long and I don't need this var anywhere else. (b) I don't want anything else messing with this variable it is ONLY for this calculation.

If I use a function node, I can do this easily because I've got access to the context as well as flow and global variables. But for something so simple, I might not want to do that or I might not have the confidence with JavaScript to do it in code.

Oops, I think I got the rules the wrong way around of course - should have set the lastTemp after the calculation and allowed for a missing value in the calculation.


Trying to think up something more realistic but I need to do some paying work for a bit :grin:

I misunderstood what you were looking for - I thought you wanted the raw context store, but it sounds like you are more interested in an option to have "node" context variables like we have flow or global. Like below:
image

The first issue that would make this more complicated to implement is that there is already a "node" typed input which could make things slightly more confusing.
image

1 Like

it adds an option to everyones menus that they don't understand (as evidenced by the debate here) - so adding confusion (and thus hurting the user experience...)

Another example. Lets say I have a sensor input that pings an update maybe once a minute and I want to output the difference between the last measurement and the current. Again, I don't really want to clutter things up (and risk accidental changes) by using a flow/global.

In a change node:

No function node needed and no contrib nodes.

I have no objection to adding node-scoped context as a built-in option for the TypedInput. That unlocks it for 3rd party nodes to start using. Whether we then add it to the list of types provided in the Change node can be debated.

3 Likes

I'm sure you remember our previous discussions of this, but for the benefit of newcomers, here are links to some of the posts:

My view on this hasn't changed in the years since, but if there are good reasons not to add this feature, I would be happy to hear them.

1 Like