Closed colinl closed 2 weeks ago
I believe sending messages from the client to the server node is supported via custom events (just need to fix the reconnection bug #913 )
Let me propose some further requirements to the server node API, to make it complete:
_client
) or to all clients which include this nodenull
in onInput
?)ui-event/ui-control
nodes, but our custom ui nodes need to be self-contained3. Expose a live list of all connected clients (which contain this node),
Clients which contain the node, or just those showing a page with the node active? Out of interest, what do you want to use that list for?
Clients which contain the node, or just those showing a page with the node active?
With the node active.
Out of interest, what do you want to use that list for?
In general, that is good info for the server node to have.
Specifically for my ui-tabulator
node, the tabulator package is instantiated and processing in the client. When in Shared (as opposed to Multi-user) mode, when I send a msg to the table node, I receive multiple identical replies (one per client), and need to collapse them by msg Id, which is very messy (or not possible in case of events).
If I had a client list, I could select any client as "spokesman" and ignore responses/events from others.
Allow code in the node's server .js file to send a message (subject to msg._client) to the node's attached clients.
base.emit(event, msg, node)
will do the trick. You just need to get reference to the UI Base in your code. If your node bind to a group via a config option, you can do group.getBase()
, otherwise a RED.getConfigNode
will be required.
It's not a well documented method, but it's used heavily in ui-control
if you need examples
Allow code in the node's client implementation to send a message to the server code so that, for example, the state store can be updated without sending a message to attached nodes, and without directly updating the datastore.
As @omrid01 pointed out - the correct approach here is a custom socket handlers
base.emit('my-event:' + node.id, msg, node)
in the server, along with
this.$socket.on('my-event:' + this.id, (msg) => {...}
in the client, works to send a message to the client, thanks.
When using a custom handler as you suggest for sending data back to the server, if in the client I use
this.$socket.emit('my-custom-event', this.id, data)
and in the server
onSocket: {
'my-custom-event': function (conn, id, msg) { ...}
}
then again that does work. However, if I have multiple nodes then all server instances receive the message from any node in the clients. Is there a way of including the node id in the event name as is done for sending to the clients? I can't use
'my-custom-event' + msg.id: function (conn, id, msg) { ...}
as that is not valid javascript.
I see that I can test the passed in id and compare it with node.id
if that is the only way.
Yeah, two options as you've detailed:
const events = {}
events['my-custom-event' + node.id] = function (conn, id, msg) { ...}
onSocket = events
onSocket: {
'my-custom-event': function (conn, id, msg) {
if (id === node.id) {
// do stuff
}
}
}
Generally SocketIO doesn't like a significant overload of handlers, so I've generally stuck with Option 2
OK. Do I need to disconnect, as is done in the client code, or is that handled automatically in the server?
Do I need to disconnect, as is done in the client code, or is that handled automatically in the server?
All handled server-side, automatically. ui-base
checks for any open handlers when you delete your last instance of your node and stops the listeners
That all seems to be working, thanks.
Hi @colinl, I think this issue can be closed, since pull request 1123 has been implemented?
Yes.
Description
Please provide methods for third party ui nodes that:
See this forum post for background information.
Have you provided an initial effort estimate for this issue?
I am no FlowFuse team member