I am retaining state information in a Dashboard 2 ui-template by saving it in a property (eg msg._mydata) in the message that gets sent back to the server. If the page is refreshed or a new browser window is opened on the page then it gets sent to the client instance of the template via the last message replay feature. Is that the recommended way to do this?
It is working ok for me, apart from the fact that sometimes I do not want to send a message on to the next nodes in the flow. It would be good if there was a way of sending a message back to the server in a way that told the server not to send it on, or is this already possible?
For big table such thing can create duplcate of database. Or I don't follow it properly?
The state is very simple, it consists of a value and an enable state. The flow sends the value in msg.payload, but the enable state is sent via a different message using msg.enabled. The 'latest msg replay feature' fails because the last message will either be a value or an enabled state, but not both. I don't want to have to join them before sending to the node as it is a dropin replacement for the standard ui- dropdown node. Ideally I would be able to put value and state into a msg property and send it back to the server, but tell the server not to send it on.
That's why I changed payload structure for compass to have both properties required. It's of course bad for user cos it takes some extra wiring and nodes in flow but keeps replay functionality correct. I'm not big fan of changing msg at frontend.
If widget's look depends on multiple properties it should actually be even clever to behave if one of them missing or don't behave at all if data is not complete. Incoming msg is not part of widget properties. It should be able to react on data and show it in the manner it is made for. Reply is only helper to not force users to create that replying system from scratch. That's all if msg remains as it was.
Yes I introduced a change of msg for dialog but that is kind of different. Get rid of msg is not as same as change it.
But who knows. This is only me and my doubts.
Exactly. That is why I want to avoid it.
It is not only look, it is functionality. It is not possible use a default value for missing data as it would then be possible for the same widget to be disabled in one browser and enabled in another viewing the same page.
Just because that was the original intention does not mean we cannot use it to the full extent of the possibility of the feature.
Ideally we should be able to do anything in a template widget that can be done in a core or contrib ui node. As far as I can see the main (only?) thing missing is that the template node does not have server side state (except via message replay). I don't know if it was a positive decision not to have server side state or whether it just was not considered. It is possible to get round the problem using message replay and 'hidden' properties, apart from the fact that it is not possible to tell the server not to send the message when its only purpose is to update the state on the server. An optional second parameter to send() to tell it not to send it on would (I think) get round the problem.
@Colin, thanks to you I was finally able to narrow down a hiccup in one of my template nodes I am trying to migrate from D1. I've been wondering if this replay feature
could be turned off, because I am reloading the data manually by sending multiple messages (traces) to a plotly graph. Or maybe I should send only one giant message and I could make use of the replay feature .. hmm.
EDIT: I think you are asking for the same thing in your previous reply? Sorry, my English.
EDIT EDIT: If only the replay message
would be marked as such, I could skip it. But an option in the template to disable this completely would be the best solution I guess.
EDIT EDIT EDIT: This seems related.
Can't be turned off but can be avoided.
Get your data out of msg.payload
and then get rid of the payload
.
And you guard it by checking if the payload property exist.
watch: {
msg: function(){
if(this.msg.payload != undefined){
this.value = this.msg.payload
this.msg.payload = null
}
}
},
Not sure I follow. It always sends an exact copy of the last message whether there is a payload or not.
It sends but you don't act on msg's where payload is missing.
Hi @hotNipi,
I kind of got lost in the data handling of D2. So the msg replay mechanism is still available in D2 you say? I had proposed at the start of the D2 developments (see here) to avoid doing that, because it gave a lot of headache for developers in D1. Thorsten did not use it anymore in Flexdash (for obvious reasons), so that is why I shared his experience in that issue. However due to free time constraints, I did not follow up this afterwards. So we do have to take the msg replay into account again while developing ui nodes?
If somebody thinks my feedback is off-topic, please don't hesitate to split my post into a new discussion!
Bart
I saw request in backlog that it should be configurable. But for sure it exists for now.
Get your data out of
msg.payload
and then get rid of thepayload
I believe that will only work if you send the message back to the server, otherwise how will the server know to change it in it's stored copy of the message? Which brings us back to being able to send a message to the server but flagging it for not being sent out.
I believe that this.msg
is reference to same object you'll get back as replay. It works obviously. Doesn't it? For dialog it works why not for others?
EDIT: Wait, Ill check something and come back with it. Cos we are talking a bit different situations maybe...
With msg watcher:
watch: {
msg: function(){
if(this.msg.payload != undefined){
You get replay message and only way to get rid of it is to send msg with payload = null
With direct socket listening:
mounted() {
this.$socket.on('msg-input:' + this.id, function (msg) {
console.log("msg from socket:",msg)
You don't get any replay messages what so ever.
Still you can listen replay by watching msg and do whatever symbiosis then
OK, that is good to know, but it isn't actually the main point of the thread, which is how to maintain state for a ui-template over, for example, page refresh. The solution I have come up with, to use replay, with a 'hidden' property of the message, works fine, except that the only way I can get it back to the server is via this.send() which I don't always want to do as it sends a message out of the node which may not be desirable.
How about HTML localStorage
. Saves data in the browser but is available after a page refresh
It would work but again - that kind of usage is like creating another instance of database.
Don't think about it as one node and one property. It's dashboard which can have a lot of things. There's no restrictions to store a chart data to local store but if you have a year amount of data for twenty charts ..
Also the state or part of the state if determined on incoming message is already old. At least couple of milliseconds. So it can't be real state of anything. The reason to rely on that data is getting smaller and smaller every second.
Opening the dashboard next Thursday and showing that stored data makes untrustworthy results and nothing more.
So the reply can help, but shouldn't taken as must or an obstacle. Every situation is a bit unique so it should be easy to choose how it should behave.
How about
HTML localStorage
That won't work for me, it has to be in the server. One of the properties is the disabled state. It is a dropdown select box that can be disabled by the flow to prevent operator input. If the node is disabled and then another user opens a browser window on the node it has to be in the disabled state. The core ui nodes presumably use server side state for such information. In fact the core dropdown node supports enable/disable so presumably it must have server side state to retain this.
Having done some more work I think there is no solution to my problem, other than to add support nodes to the flow.
The fundamental problem is that I need to build up the state of the widget based on a sequence of messages coming in. As I understand it there is no server side storage associated with the template other than the configuration and the last message sent. My proposed solution was to build up the state client side and include the state in messages sent by the node, such that it gets saved in the 'last message sent' and then if the browser is refreshed, or a new client connects, the state information is available. The problem is that that fails completely if there is no client connected.
So unless someone can offer a solution I have no option other than do something like adding a Join node in front of each widget and making sure that the messages have appropriate topics.
You have reached to same conclusion I had. Hope that maybe at some point the storage api reaches to ui_template
node somehow...
I think the template needs another section, which is run in the server. So effectively the template has an attached Function node which can save state and can communicate with the attached clients as appropriate.
If core and contrib widgets have the same restriction then that means that there may be no solution to issue 622 and I think the other nodes that have state, such as dropdown and text input, will also have the problem that enabling/disabling will destroy the current state.
I don't know whether D1 had that problem or not....
[Edit] With D1 for the same tests as described for issue 622, the switch does not lose its state over enable/disable, though it does lose the saved topic. I deduce from that that D1 must have some state storage in the server, other than the last message sent. I also deduce that losing the topic is not a serious issue as apparently no-one has noticed it. I think that losing the switch state as D2 does is not good.