Update ui-table if Tab is visible

I am sitting over this for some time now. I want to update the contents of my ui-table if the tab where it is located, is visible.

So far I put this together:

Problems that I have:

1.Everytime I open the Tab with the UI-Table, a new connection to the websocket is established.
2. At the moment it work very inconsistenly, sometimes I get an output directly after entering or leaving the tab, sometimes nothing and sometimes I get several messages at once for one tab browse.

Hope someone here can help me to fix this.

Edit: Since I tend to overthink things, I would be really happy if somebody could offer a different solution to update the contents if the tab is visible.

Content of my function-node:

// Create an array to store connected WebSocket clients
if (!flow.get('clients')) {
    flow.set('clients', []);
}

// Function to handle new WebSocket connections
function handleNewConnection(connection) {
    // Add the connection to the clients array
    flow.get('clients').push(connection);

    // Send a welcome message to the new connection
    connection.send(JSON.stringify({ message: 'Welcome!' }));

    // Handle incoming messages from the client
    connection.on('message', function (message) {
        // Process the received message
        var msg = JSON.parse(message);

        // Perform actions based on the tab's active state
        // Example: Send the tab's active state to debug output
        node.send({ payload: msg.active });
    });

    // Handle WebSocket connection closure
    connection.on('close', function () {
        // Remove the connection from the clients array
        var clients = flow.get('clients');
        var index = clients.indexOf(connection);
        if (index !== -1) {
            clients.splice(index, 1);
        }
    });
}

// Check if it's a new WebSocket connection
if (msg.req && msg.req.websocket) {
    // Handle new WebSocket connections
    handleNewConnection(msg.req.websocket);
}

// Clean up the clients array when the flow is deployed
node.on('close', function () {
    flow.set('clients', []);
});
return msg;

Content of my UI-Template:

<script>
 
// Create a WebSocket connection
       
var socket = new WebSocket('ws://172.16.19.10:1880/tab-state'); 
//if(!window.socket){socket = new WebSocket('ws://172.16.19.10:1880/tab-state')};

// Send the tab's active state when it changes
document.addEventListener('visibilitychange', function() {
  var isActive = !document.hidden;
  socket.send(JSON.stringify({ active: isActive }));
});

// Handle messages from the server
socket.addEventListener('message', function(event) {
  var message = JSON.parse(event.data);
  // Handle server messages if needed
});

// Handle focus and blur events
window.addEventListener('focus', function() {
  socket.send(JSON.stringify({ active: true }));
});

window.addEventListener('blur', function() {
  socket.send(JSON.stringify({ active: false }));
});
</script>

sample Debug-node output:

{"payload":"{\"active\":false}","_session":{"type":"websocket","id":"3ab2348f68c3983d"},"_msgid":"69c916af38801171"}

last but not least a flow snippet:

[
    {
        "id": "dcf88caf4455995d",
        "type": "ui_template",
        "z": "6f89e794df0518b3",
        "group": "0375aefee90144ba",
        "name": "WebsocketTemplate",
        "order": 4,
        "width": 0,
        "height": 0,
        "format": "<script>\n \n// Create a WebSocket connection\n       \nvar socket = new WebSocket('ws://172.16.19.10:1880/tab-state'); \n//if(!window.socket){socket = new WebSocket('ws://172.16.19.10:1880/tab-state')};\n\n// Send the tab's active state when it changes\ndocument.addEventListener('visibilitychange', function() {\n  var isActive = !document.hidden;\n  socket.send(JSON.stringify({ active: isActive }));\n});\n\n// Handle messages from the server\nsocket.addEventListener('message', function(event) {\n  var message = JSON.parse(event.data);\n  // Handle server messages if needed\n});\n\n// Handle focus and blur events\nwindow.addEventListener('focus', function() {\n  socket.send(JSON.stringify({ active: true }));\n});\n\nwindow.addEventListener('blur', function() {\n  socket.send(JSON.stringify({ active: false }));\n});\n</script>",
        "storeOutMessages": true,
        "fwdInMessages": true,
        "resendOnRefresh": true,
        "templateScope": "local",
        "className": "",
        "x": 820,
        "y": 140,
        "wires": [
            []
        ]
    },
    {
        "id": "919b47275e449b65",
        "type": "debug",
        "z": "6f89e794df0518b3",
        "name": "debug output from websocket",
        "active": true,
        "tosidebar": true,
        "console": false,
        "tostatus": false,
        "complete": "true",
        "targetType": "full",
        "statusVal": "",
        "statusType": "auto",
        "x": 1350,
        "y": 80,
        "wires": []
    },
    {
        "id": "e170c5f9f040904f",
        "type": "websocket in",
        "z": "6f89e794df0518b3",
        "name": "",
        "server": "d81154f0843a22d0",
        "client": "",
        "x": 690,
        "y": 80,
        "wires": [
            [
                "9fe352d21bee20cc"
            ]
        ]
    },
    {
        "id": "9fe352d21bee20cc",
        "type": "function",
        "z": "6f89e794df0518b3",
        "name": "function 1",
        "func": "// Create an array to store connected WebSocket clients\nif (!flow.get('clients')) {\n    flow.set('clients', []);\n}\n\n// Function to handle new WebSocket connections\nfunction handleNewConnection(connection) {\n    // Add the connection to the clients array\n    flow.get('clients').push(connection);\n\n    // Send a welcome message to the new connection\n    connection.send(JSON.stringify({ message: 'Welcome!' }));\n\n    // Handle incoming messages from the client\n    connection.on('message', function (message) {\n        // Process the received message\n        var msg = JSON.parse(message);\n\n        // Perform actions based on the tab's active state\n        // Example: Send the tab's active state to debug output\n        node.send({ payload: msg.active });\n    });\n\n    // Handle WebSocket connection closure\n    connection.on('close', function () {\n        // Remove the connection from the clients array\n        var clients = flow.get('clients');\n        var index = clients.indexOf(connection);\n        if (index !== -1) {\n            clients.splice(index, 1);\n        }\n    });\n}\n\n// Check if it's a new WebSocket connection\nif (msg.req && msg.req.websocket) {\n    // Handle new WebSocket connections\n    handleNewConnection(msg.req.websocket);\n}\n\n// Clean up the clients array when the flow is deployed\nnode.on('close', function () {\n    flow.set('clients', []);\n});\nreturn msg;",
        "outputs": 1,
        "noerr": 0,
        "initialize": "",
        "finalize": "",
        "libs": [],
        "x": 860,
        "y": 80,
        "wires": [
            [
                "04bb2080c44cce84"
            ]
        ]
    },
    {
        "id": "04bb2080c44cce84",
        "type": "switch",
        "z": "6f89e794df0518b3",
        "name": "",
        "property": "payload",
        "propertyType": "msg",
        "rules": [
            {
                "t": "cont",
                "v": "true",
                "vt": "str"
            },
            {
                "t": "cont",
                "v": "false",
                "vt": "str"
            }
        ],
        "checkall": "true",
        "repair": false,
        "outputs": 2,
        "x": 1050,
        "y": 80,
        "wires": [
            [
                "257f86d240d00c36"
            ],
            [
                "4bb335fd3da45565"
            ]
        ]
    },
    {
        "id": "257f86d240d00c36",
        "type": "delay",
        "z": "6f89e794df0518b3",
        "name": "",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "outputs": 1,
        "x": 1175,
        "y": 60,
        "wires": [
            [
                "919b47275e449b65"
            ]
        ],
        "l": false
    },
    {
        "id": "4bb335fd3da45565",
        "type": "delay",
        "z": "6f89e794df0518b3",
        "name": "",
        "pauseType": "rate",
        "timeout": "5",
        "timeoutUnits": "seconds",
        "rate": "1",
        "nbRateUnits": "1",
        "rateUnits": "second",
        "randomFirst": "1",
        "randomLast": "5",
        "randomUnits": "seconds",
        "drop": true,
        "allowrate": false,
        "outputs": 1,
        "x": 1175,
        "y": 100,
        "wires": [
            [
                "919b47275e449b65"
            ]
        ],
        "l": false
    },
    {
        "id": "0375aefee90144ba",
        "type": "ui_group",
        "name": "Meldungen",
        "tab": "9a1ccd72ee604b50",
        "order": 2,
        "disp": true,
        "width": "16",
        "collapse": false,
        "className": ""
    },
    {
        "id": "d81154f0843a22d0",
        "type": "websocket-listener",
        "path": "/tab-state",
        "wholemsg": "false"
    },
    {
        "id": "9a1ccd72ee604b50",
        "type": "ui_tab",
        "name": "Meldungen",
        "icon": "mi-notifications",
        "order": 8,
        "disabled": false,
        "hidden": false
    }
]

Seems over complicated.
You probably do not need to use websockets.
Here is an example the table only updates when the tab it is on is visible

[{"id":"14ac1f7d6efe1fa3","type":"inject","z":"b9860b4b9de8c8da","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"2","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"[{\"one\":1,\"two\":2},{\"one\":4,\"two\":5}]","payloadType":"json","x":160,"y":3540,"wires":[["a36e47b26c37a21c"]]},{"id":"a36e47b26c37a21c","type":"switch","z":"b9860b4b9de8c8da","name":"","property":"visibility.demo","propertyType":"flow","rules":[{"t":"true"}],"checkall":"true","repair":false,"outputs":1,"x":310,"y":3540,"wires":[["1340d3a79960f451"]]},{"id":"1340d3a79960f451","type":"function","z":"b9860b4b9de8c8da","name":"function 25","func":"let tableData = flow.get(\"savedData\") || [];\nlet new_row = {\n    \"one\": new Date().toISOString(),\n    \"two\": (Math.random()*2).toFixed(1),\n};\n\ntableData.unshift(new_row);\nif (tableData.length > 9){\ntableData.pop();\n}\nmsg.payload = {\n    command: \"replaceData\",\n    arguments: [\n        tableData,\n        true\n    ],\n    returnPromise: true\n}\n\nflow.set(\"savedData\", tableData);\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":470,"y":3540,"wires":[["57590ede03d46c80","54448e555b8c54fb"]]},{"id":"57590ede03d46c80","type":"ui_table","z":"b9860b4b9de8c8da","group":"2d4fe667.28f8ba","name":"","order":24,"width":"12","height":"9","columns":[],"outputs":0,"cts":false,"x":650,"y":3520,"wires":[]},{"id":"54448e555b8c54fb","type":"debug","z":"b9860b4b9de8c8da","name":"debug 302","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":670,"y":3600,"wires":[]},{"id":"37eaa50350510d99","type":"change","z":"b9860b4b9de8c8da","name":"","rules":[{"t":"set","p":"visibility[msg.topic]","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":420,"y":3660,"wires":[["54448e555b8c54fb"]]},{"id":"dcf88caf4455995d","type":"ui_template","z":"b9860b4b9de8c8da","group":"2d4fe667.28f8ba","name":"WebsocketTemplate","order":4,"width":0,"height":0,"format":"\n<script>\n  (function(scope) {\n    document.addEventListener(\"visibilitychange\", function (event) {\n        scope.send({payload: !document.hidden, topic: \"demo\"});\n    });\n})(scope);\n</script>","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":160,"y":3660,"wires":[["37eaa50350510d99"]]},{"id":"2d4fe667.28f8ba","type":"ui_group","name":"demo","tab":"1caa8458.b17814","order":2,"disp":true,"width":"12","collapse":false,"className":""},{"id":"1caa8458.b17814","type":"ui_tab","name":"Demo","icon":"dashboard","order":1,"disabled":false,"hidden":false}]
1 Like

I tried your flow, but I don´t get any output from the template when switching tabs. I put the template in the same group as the ui-table. Anything else to check for?

Working here, have you tried refreshing the browser. Or initialising the table with data. Would need more info to help more, how did you edit the flow etc.
here is table i changed tabs twice you can see the time gaps.

I tried refreshing the browser, but that didn´t seem to habe any effect.
I broke it down to this:

So for my understanding, I put the Template in the same group,in the same tab, as the ui-table and would expect messages to arrive at the debug-node when switching tabs, but that doesn´t work.
Tested with Firefox and Chrome if that is of interest?

Works in firefox and chrome here.
You still have not supplied any useful info, can not tell anything from a image.
My flow consisted of 7 nodes, if you run it un edited does it work?

Doesnt work unedited. I found out something strange. So if I run this:

And switch between tabs, first nothing happens. Then, if i logout(win+L) and log back in, my debug-window looks like this:

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