UI-Table vanishes on browser reload

Hello guys,

I've got a reloading issue with my UI-Table that is directly filled from an array.

  1. In an injection node I have an SELECT query that MySQL-DB responds with a proper result set.
  2. The data array is forwarded to a function node which adds options and column definitions to the payload
  3. The "etable" node (from node-red-contrib-ui-etable) presents a nice looking table - but ONLY after I have clicked the "deploy" in the node-red flow!
  4. On a browser reload of the UI the table is no more filled and not even showing up. In that case the debug channel does not show any payload coming from the DB query. :exclamation:

Here's the code in my function node:

msg = { 
    payload: msg.payload,
    config: {
        options: {
                    "movableColumns": true,
                    "resizableColumns": true,
                    "selectable": 1,
                    "responsiveLayout": "collapse",
                    "autoResize": true,
                    "layout": "fitColumns",
                    "pagination": "local",
                    "height": "800px",
                    "groupBy": "system",
                    "groupStartOpen": true
        },
        columns: [
                    { title:"Id", field:"SIGNAL_ID", align:"center", editor:"select", width:60 },
                    { title:"Symbol", field:"SYMBOL", align:"center", width:120 },
                    { title:"Signal", field:"SIGNAL_TYPE", align:"center", width:100 },
                    { title:"Direction", field:"POS_TYPE", align:"center", width:60 },
                    { title:"Entry", field:"ENTRY_PRICE", align:"center", width:100 },
                    { title:"Date", field:"TIME", align:"center", width:180 },
                    { title:"SL", field:"SL", align:"center", width:100 },
                    { title:"TP", field:"TP", align:"center", width:100 },
                    { title:"Vol.", field:"INITIAL_VOL", align:"center", width:80 }
                ]
    },
    //ui_control: {'callback':'rowSelectionChanged','rowSelection':'Name' }
}

return msg;

Does anyone have an idea why the reload leads to a blank table?

As you can see, I have tried with a delay node (in German: Verzögerung), in order to kind of drop the data with a delay, hoping that would help..

Btw. should I rather go with the ui-table from node-red-node-ui-table?

Cheers,
Marcel

Hi Marcel, thanks for pointing out the existence of the node-red-contrib-ui-etable. I was not aware of it. I will give it a try (when time allows).

I find that node-red-node-ui-table is awesome. I simply could not develop some applications without it. However there are a couple of annoyances with this node. First one being that the auto reload is not predictable. I don't know if this is due to the complexity linked to the virtual DOM on tabulator.js or something I am not handling correctly. Perhaps the issue is similar to the one you are facing with node-red-contrib-ui-etable. The work around I put in place is using an array destructuring in the function node that is in front of the ui_table node. Somehow doing a shallow array copy seems to fix the issue.

Lets say that the array you pass to the ui_table is on the variable arr the you could try using this command in the function node: msg.payload = [...arr];

The second annoyance is that some kind of changes in the ui_table configuration require a stop-start in Node-RED, otherwise the changes will not take effect. This is the reason I will be willing to try node-red-contrib-ui-etable.

1 Like

fixes and enhancement Pull requests to ui-table most welcome !

Hi Andrej,

thanks for your reply!

As you can see, I have changed the flow so that the output from the database is interrupted. When I redeploy, the dashboard still shows a filled table nonetheless. It seems that this etable is caching data, but this is just a guess.

I tried to save the array from that DB-node into an intermediate variable like so

var arr = msg.payload;
msg = { 
    payload: arr,
    config: {
        options: {
                    ...
        },
        columns: ...
    },
}

return msg;

However this doesn't change that weird behavior neither.

I did not understand what you mean with that 2nd annoyance. Could you elaborate this on an example? Particularly, what do you mean with 'stop-start'?

Cheers,
Marcel

P.S.: If you are looking into the etable node here's an example with static data from the author:

I mean that some changes on the table definition, via ui_control, appears to not have effect but they work after reinitialization the runtime with node-red-stop and node-red-start commands. It maybe some cache issue but I could not fully identify the root cause.

Having a look in your code something that catch my attention is that you are redefining the table in every message sent to the ui_table node. Perhaps it works fine but it just looks strange (not saying it is an issue). Normally I define the table once and any other payload would be used only to populate the table. I illustrate this point below for clarity. The table will receive only one single configuration message from leg number "1" (at the startup of the flow). All other updates comes from leg number 2.

Now, another thing in your code.

msg = { 
    payload: msg.payload,
    config: {

This is the same as msg.payload = msg.payload. I don´t see the purpose.

Question: Did you try to test the behaviour of the uitable using a simple array instead of data retrieved from the database ? I guess the source of the data is not meaningful so you should be able to reproduce the issue in a simpler way (and perhaps share in the forum the simplified flow).

1 Like

Yes, I tried the behavior on static array data. It's from the example1 as linked above. It's a very simple flow I have placed on the same Dashboard element (for that I have disabled all nodes regarding the dynamic data coming from the MySQL DB). The behavior was proper, i.e. reloading the browser tab lead to immediately displaying the array in the table again.

But I have just found out something that confuses me about the injection node. The following flow is from the bespoken example1 from the author of the etable node:

image

The disconnection between injection and function is intentional because I was doubting something.. and I was right:
After I reloaded the UI browser tab no output is shown on the debug channel - despite the injection node places {"a":"wombat","b":"NEW"} on the msg.paylod.

Oh my! And I thought the injection nodes are triggered on every UI reload, too. Looks like this is not the case and I have learned something new again

So do I have to send data periodically to the dashboard? Is that really necessary? :thinking:

I have noticed that edits to disable save state and disable replay saved state to survive full deployment and a browser refresh retains the saved state.

Node-red has to be restarted in my experience at the moment.

@Ozpos What do you mean with "Edits to disable save state" and "disable replay saved state"? Are you referring to context stores as in https://nodered.org/docs/user-guide/context#context-stores?

@Andrei In this flow I have employed a ui button as you did.

Pressing "Refresh" in my dashboard leads to the array output as indicated in the debug channel - BUT, it's not shown/updated in the table of the dashboard - it just remains empty. Looks like it must be some sort of internal cache thing ... or not? I'm confused. I'll take a break, checking in tomorrow - Good night!

Yes I was referring to context store. It seems as though the two could be connected.

On a browser reload / or initially landing on the dashboard, it seems using a "refresh button" seems to be the only way to properly load the data into the table. Note, that the function node is again between the MySQL and etable nodes.

Looks like that's a workaround for now that I can happily live with. I guess the only other alternative would be to set an interval to fire that injection node every x seconds.

I found my errors why the table did not render in the dashboard:

1. Error: Regarding that code snippet from above:

msg = { 
    payload: msg.payload,
    options: { ... },
    columns: [ { /*col1 definitions*/  }, /* ... */ { /*colN definitions*/  } ]
}
return msg;

With msg = { ... } I tried to rebuild the whole message object (no good, I know :slight_smile: ). In a moment of a brain fart I had removed "payload: msg. payload" which ofc lead to an empty table. Bah!
Well, the working code in my function now node looks like this:

msg.config = {
    options: { ... },
    columns: [ { /*col1 definitions*/  }, /* ... */ { /*colN definitions*/  } ]
}
return msg;

2. Error: Defining a column in this way is wrong:

                {
                    title: "Id",
                    field: "SIGNAL_ID",
                    align: "center",
                    editor: "select",
                    width: 60
                },

Instead this one is correct:

                {
                    "title": "Id",
                    "field": "SIGNAL_ID",
                    "align": "center",
                    "editor": "select",
                    "width": 60
                },

With these errors fixed, the table is now initially properly filled with data and also during a browser reload! (The refresh button is no more required, though nice to have)

At least I hope - with this closing post, to help the next newbie not to make the same mistakes. :wink:

Hi @CreativeWarlock, thank you for documenting the fix so well.
Could you please tell me in which node error No. 2 was discovered ?

The 2nd error happened in the function node, that one before the etable node.

Thank you. Not being a js programmer myself Is it safe to say that one could use {"somekey": ... everywhere ?