Not understanding how/when Dashboard UI updated

When the Dashboard UI is opened in the browser, this flow is not updated:

I "assumed" it would get updated by starting with an injection node with the "inject once after .1 seconds" checked. This is not the case.

So my conceptual model on what happens when the UI is opened or refreshed in the browser is incorrect.

How does UI update work?

THank you.

I use the ui_control node (connect event only) to start flows when the dashboard is started.

Can you post an example flow that shows the problem? If the flow has sent a value to a text node it should not be necessary to rerun it when you open the browser.

Thank you @Colin . I apologize if I'm mistaken, the flow was posted in my original post. I have an injection node set to fire off at "once after .1 seconds" I assumed the firing off would occur when the Dashboard's UI is invoked in the browser or the Dashboard UI web page is refreshed.

So there is no change in value coming in. The change in value comes in the function node that follows the injection node. Here, I figure out the difference from when the user started their plant in soil and then display the Time Growing in the text UI node. It is the Time Growing that is not updating upon page refresh or when the URL is initially invoked.

Thank you.

Thank you @rakgupta I started playing around with the ui_control node. I appreciate your help.

1 Like

In my flow, the "Manual Startup" inject node is only if I want to start the flow manually. It doesn't do anything otherwise. The ui_control node is the one that actually starts the flow when the user starts the dashboard ui. Hope that helps

The flow shown above also does a refresh when the user changes tabs. Here is the flow:

[{"id":"c319afa4.557968","type":"group","z":"c1b9d37f.b6443","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["14ce4cc6.d66e1b","130b08c0.946dff","a0cd749f.8635c8","ab9a436b.1dbad8","7ac12a79.c2e98c","3f58c8f3.cdbed","dd4ec3f6.31e2a","cb47b44.cab4c48"],"x":92.33334350585938,"y":92.6666488647461,"w":1027.6665344238281,"h":210.33335876464844},{"id":"14ce4cc6.d66e1b","type":"ui_ui_control","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Startup","events":"connect","x":422.6666564941406,"y":190.66663551330566,"wires":[["3f58c8f3.cdbed"]]},{"id":"130b08c0.946dff","type":"link out","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Dashboard Startup - Out","links":["2b3b452f.1dac22","411c1b85.f50ec4","480b0328.37263c","4ef418da.8ab538","c07805cd.355d4","c41552b6.8571a","c64a8499.028398","d294caea.d30598","f72fda03.2de5e8","95c28f77.44567","57d384c3.4321e4","11d3a079.a43b28","a7c22f20.f7faa","df3da41b.01b6c","17be7d99.8c0312","acfe7184.9dee58","a38b5895.f8c6a8","ae0a9fb7.a3c5c8"],"x":884.3332214355469,"y":139.66661834716797,"wires":[],"l":true},{"id":"a0cd749f.8635c8","type":"comment","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Change log","info":"2021-03-24: Created to replace individual statup ui_control nodes for each tab\n2021-04-17: Added logic to refresh current tab on \"change\" tab event, pull data only on \"connect\" event.","x":211.33334350585938,"y":262.00000762939453,"wires":[]},{"id":"ab9a436b.1dbad8","type":"inject","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Manual Startup","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":222.33334350585938,"y":191.00000953674316,"wires":[["14ce4cc6.d66e1b"]]},{"id":"7ac12a79.c2e98c","type":"comment","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Dashboard Startup","info":"","x":208.33334350585938,"y":133.6666488647461,"wires":[]},{"id":"3f58c8f3.cdbed","type":"switch","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Connect or Change","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"connect","vt":"str"},{"t":"eq","v":"change","vt":"str"}],"checkall":"true","repair":false,"outputs":2,"x":631.3333892822266,"y":191.00001525878906,"wires":[["130b08c0.946dff"],["dd4ec3f6.31e2a"]]},{"id":"dd4ec3f6.31e2a","type":"change","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Refresh Tab","rules":[{"t":"set","p":"payload","pt":"msg","to":"","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":841,"y":236.66665649414062,"wires":[["cb47b44.cab4c48"]]},{"id":"cb47b44.cab4c48","type":"ui_ui_control","z":"c1b9d37f.b6443","g":"c319afa4.557968","name":"Refresh tab","events":"change","x":1023.9998779296875,"y":237.00015258789062,"wires":[[]]}]

You just posted a screenshot. I meant you to create a simple flow with an Inject node, into a function node and then to a text node. Select those nodes and export to clipboard using the menu. Paste it here, using the </> button at the top of the entry window when pasting it. You should not need to use a control node.

For example, here is a flow that works for me. Copy it from here (a Copy button will pop up at the right hand end if you hover over it) and Import it into your flows. If you then deploy it and open the dashboard on the appropriate tab you should see the text, and it should not go away if you refresh the browser.

[{"id":"9903f59fb016ec4c","type":"inject","z":"1f1050e0d58da653","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":true,"onceDelay":0.1,"topic":"","payloadType":"date","x":160,"y":900,"wires":[["6ed298269ae995a7"]]},{"id":"6ed298269ae995a7","type":"function","z":"1f1050e0d58da653","name":"Data","func":"msg.payload = \"Some text\"\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":320,"y":900,"wires":[["e03bda318e5624aa"]]},{"id":"e03bda318e5624aa","type":"ui_text","z":"1f1050e0d58da653","group":"903a6ab8.4f4ca8","order":1,"width":0,"height":0,"name":"","label":"text","format":"{{msg.payload}}","layout":"row-spread","className":"","x":490,"y":900,"wires":[]},{"id":"903a6ab8.4f4ca8","type":"ui_group","name":"Home","tab":"e2e6f4f5.56f91","order":1,"disp":false,"width":"6","collapse":false,"className":""},{"id":"e2e6f4f5.56f91","type":"ui_tab","name":"Homet","icon":"dashboard","order":3,"disabled":false,"hidden":false}]

Thank you @Colin. The flow you posted works because a deploy causes the injection node to run after .1 seconds. In my case, the difference is in the function, I am calculating the number of weeks/days that have passed since a start date. I do this by figuring out the current data (now()) and doing "date math."

This means I do not use a deploy to update. Rather I open the UI and expect the field to have run just by opening the UI, not depending on a deploy.

1 Like

Can you post a simple example that fails, so I can try here?

[Edit] do you mean that nothing will have been written to ui node ever? In that case that is the problem. If you don't want it to write anything to the ui node until you open the browser then yes, you will have to use a ui_control node to detect it and write the required value.

Hi @Colin
First - thank you.
I apologize for not being clear. I have a text node (Time Growing) that shows the weeks and days a plant has been growing since a start date that was entered when the UI is first used. Each day when the UI is open, the Time Growing should update by a day. Now, it does not update unless I go into the flow and manually inject.

Here is the flow:

[
    {
        "id": "d382c68206a2053e",
        "type": "ui_text",
        "z": "e276300d7cbaa457",
        "group": "7a0c3262d7dd5dc0",
        "order": 3,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Time Growing",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "x": 840,
        "y": 620,
        "wires": []
    },
    {
        "id": "e31c34c23ffe518b",
        "type": "function",
        "z": "e276300d7cbaa457",
        "name": "figure out weeks/days since start of grow",
        "func": "\nvar oneDay = 1000*60*60*24;\n\n\n\nvar date_today = new Date();\nvar date_grow_start = new Date(flow.get(\"grow_start_date\")+1000);\n// To calculate the time difference of two dates\nvar diff = date_today.getTime() - date_grow_start.getTime();\nnode.warn(\"time diff: \" + diff);\n// To calculate the no. of days between two dates\nflow.set(\"weeks\",Math.floor((diff/oneDay)/7));\nflow.set(\"days\", Math.round((diff/oneDay)%7));\nflow.set(\"growth_stage\",flow.get(\"weeks\") < 4 ? \"baby\" : flow.get(\"weeks\")  < 9 ? \"veg\" : \"flower\");\n\n//node.warn(\"Growth stage is \"+flow.get(\"growth_stage\"))\nmsg.payload = flow.get(\"weeks\") + \" weeks, \" + flow.get(\"days\") + \" days\";\n\nnode.warn(flow.get(\"weeks\") + \" weeks, \" + flow.get(\"days\") + \" days\")\n\n\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 480,
        "y": 600,
        "wires": [
            [
                "d382c68206a2053e",
                "b303ac47d0817e07",
                "6d3c0fd9f0011a14"
            ]
        ]
    },
    {
        "id": "f2f31efacf7ce175",
        "type": "comment",
        "z": "e276300d7cbaa457",
        "name": "Set the growth stage to be either baby, veg, or flower.",
        "info": "",
        "x": 1280,
        "y": 640,
        "wires": []
    },
    {
        "id": "23cd491833e7aa2f",
        "type": "ui_text",
        "z": "e276300d7cbaa457",
        "group": "7a0c3262d7dd5dc0",
        "order": 5,
        "width": 3,
        "height": 1,
        "name": "",
        "label": "Growth Stage",
        "format": "{{msg.payload}}",
        "layout": "col-center",
        "className": "",
        "x": 1240,
        "y": 600,
        "wires": []
    },
    {
        "id": "b303ac47d0817e07",
        "type": "change",
        "z": "e276300d7cbaa457",
        "name": "",
        "rules": [
            {
                "t": "set",
                "p": "payload",
                "pt": "msg",
                "to": "growth_stage",
                "tot": "flow"
            }
        ],
        "action": "",
        "property": "",
        "from": "",
        "to": "",
        "reg": false,
        "x": 1030,
        "y": 600,
        "wires": [
            [
                "23cd491833e7aa2f"
            ]
        ]
    },
    {
        "id": "f1f3082e33d2de95",
        "type": "comment",
        "z": "e276300d7cbaa457",
        "name": "Note: Updating in influx means keeping all entries in the row the same except the entry to change.",
        "info": "",
        "x": 1070,
        "y": 560,
        "wires": []
    },
    {
        "id": "766ae31041bcf5c9",
        "type": "inject",
        "z": "e276300d7cbaa457",
        "name": "",
        "props": [
            {
                "p": "payload"
            },
            {
                "p": "topic",
                "vt": "str"
            }
        ],
        "repeat": "",
        "crontab": "",
        "once": false,
        "onceDelay": 0.1,
        "topic": "",
        "payload": "",
        "payloadType": "date",
        "x": 160,
        "y": 600,
        "wires": [
            [
                "e31c34c23ffe518b"
            ]
        ]
    },
    {
        "id": "7a0c3262d7dd5dc0",
        "type": "ui_group",
        "name": "Buddy Stuff",
        "tab": "1ff97cd4.681d5b",
        "order": 1,
        "disp": true,
        "width": 16,
        "collapse": false,
        "className": ""
    },
    {
        "id": "1ff97cd4.681d5b",
        "type": "ui_tab",
        "name": "Grow Buddy",
        "icon": "dashboard",
        "order": 37,
        "disabled": false,
        "hidden": false
    }
]

As you have it in that flow the inject will never by triggered (unless manually pressed) so the ui nodes will never have anything written on them. It is nothing to do with opening or refreshing the browser, as you have not sent anything to be displayed.

If you want the ui nodes to be written to when you open the browser then yes, you will need to us a ui-control node to detect the browser operation and write to the ui nodes.

You could just set the trigger node to fire every 5 minutes. Then it would always show the right day (except possibly during the first 5 minutes of the day).

Why not just fire the inject just after midnight every day ?

image

Yes, that should do it, combined with Inject once at startup, to cope with a node-red restart.

OOH - good idea. Thank you very much.

I wanted to avoid one more thing constantly polling. Perhaps that's not a big deal?

Thank you. Seems it is taking me awhile to understand code -> UI.

You can think of the node-red flows building the dashboard and maintaining the text, graphics etc. Then when you open the browser you are just opening a window that you can look through to see what node-red has built. That isn't entirely an accurate description, but for understanding the basic operation it is a reasonable approximation.

Thank you. It seems to me there is a bit of a conceptual disconnect between the flow/code and the browser UI. Ideally I would think a property on the UI node could be set that says to refresh on every browser page opening of it or refresh. Control UI doesn't seem designed for this type of scenario. I ended up using two inject nodes as proposed.