Hide tab with UI control not working since nodered update

Hi,
I updated Nodered to 1.1.3 recently and found that a feature where I hide tabs with UI control node was not working anymore.
Do others experience the same problem ?
Thank you

Are you using the latest version of the dashboard? It may not help but it would be good to rule that out. If it does fail with the latest version add a debug node showing what it going to the control node, set to Show Complete Message, post the results here and tell us what it is not doing.

Can you post the flow?

Hi,
My original flow is quite a mess but I made this example flow.
I'm using v1.1.3 of Nodered and the dashboard module is up to date.
When I use the manual toggles on the tab settings enable/disable hide/show works properly.
Do I miss something ?
None of the hide/show or enable/disable works either with tabs nor groups.
Thank you

[{"id":"f68e9dd6.332eb","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"13768a63.80f336","type":"inject","z":"f68e9dd6.332eb","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":100,"wires":[["d1bd954e.dd8648"]]},{"id":"d1bd954e.dd8648","type":"function","z":"f68e9dd6.332eb","name":"","func":"msg.payload = {\"tabs\": {\"disable\": [\"My Tab\"]}}\n//msg.payload = {\"tabs\": {\"hide\": [\"My Tab\"]}}\n//msg.payload = {\"group\": {\"hide\": [\"My Group\"]}}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":310,"y":100,"wires":[["9f6606bb.bb8b78","feab2e77.aaa0c"]]},{"id":"9f6606bb.bb8b78","type":"ui_ui_control","z":"f68e9dd6.332eb","name":"","x":500,"y":100,"wires":[["84efc00e.069a4"]]},{"id":"1d4c42a8.129fed","type":"ui_button","z":"f68e9dd6.332eb","name":"","group":"47a02a2e.a13ca4","order":0,"width":0,"height":0,"passthru":false,"label":"button","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":130,"y":140,"wires":[["d1bd954e.dd8648"]]},{"id":"84efc00e.069a4","type":"debug","z":"f68e9dd6.332eb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":670,"y":100,"wires":[]},{"id":"feab2e77.aaa0c","type":"debug","z":"f68e9dd6.332eb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":490,"y":60,"wires":[]},{"id":"47a02a2e.a13ca4","type":"ui_group","z":"","name":"My Group","tab":"659c85a9.ff391c","order":1,"disp":true,"width":"6","collapse":false},{"id":"659c85a9.ff391c","type":"ui_tab","z":"","name":"My Tab","icon":"dashboard","disabled":false,"hidden":false}]

You have to replace spaces in the names with underscore characters, that is mentioned in the help text for the ui node but it isn't that clear.

The tab I'm working with is called "Camera" so has no space inside, I changed my example flow with MyTab and MyGroup instead of My Tab and My Group but it's not working either.

[{"id":"f68e9dd6.332eb","type":"tab","label":"Flow 1","disabled":false,"info":""},{"id":"13768a63.80f336","type":"inject","z":"f68e9dd6.332eb","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":130,"y":100,"wires":[["d1bd954e.dd8648"]]},{"id":"d1bd954e.dd8648","type":"function","z":"f68e9dd6.332eb","name":"","func":"//msg.payload = {\"tabs\": {\"disable\": [\"MyTab\"]}}\nmsg.payload = {\"tabs\": {\"hide\": [\"MyTab\"]}}\n//msg.payload = {\"group\": {\"hide\": [\"MyGroup\"]}}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":310,"y":100,"wires":[["9f6606bb.bb8b78","feab2e77.aaa0c"]]},{"id":"9f6606bb.bb8b78","type":"ui_ui_control","z":"f68e9dd6.332eb","name":"","x":500,"y":100,"wires":[["84efc00e.069a4"]]},{"id":"1d4c42a8.129fed","type":"ui_button","z":"f68e9dd6.332eb","name":"","group":"47a02a2e.a13ca4","order":0,"width":0,"height":0,"passthru":false,"label":"button","tooltip":"","color":"","bgcolor":"","icon":"","payload":"","payloadType":"str","topic":"","x":130,"y":140,"wires":[["d1bd954e.dd8648"]]},{"id":"84efc00e.069a4","type":"debug","z":"f68e9dd6.332eb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":670,"y":100,"wires":[]},{"id":"feab2e77.aaa0c","type":"debug","z":"f68e9dd6.332eb","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":490,"y":60,"wires":[]},{"id":"47a02a2e.a13ca4","type":"ui_group","z":"","name":"MyGroup","tab":"659c85a9.ff391c","order":1,"disp":true,"width":"6","collapse":false},{"id":"659c85a9.ff391c","type":"ui_tab","z":"","name":"MyTab","icon":"dashboard","disabled":false,"hidden":false}]

It is working for me, except that if you hide the tab using the button, or using the inject when you are actually on that tab, then it removes it from the menu but it remains visible as it is currently on the screen. I don't know whether that is what is supposed to happen or not. Is that what you are seeing?

Nothing happens for me even if I'm on another tab.
Do you have an output from the ui_control node when clicking the button or inject ?
Because I don't have any.

Do you mean that after clicking the Inject node in your test flow that it still appears in the menu?
There is no output because you haven't selected anything to be output in the control node config.
What hardware/OS are you running on?
Stop node-red and then start it in a terminal and copy/paste the startup log here. Use the same method when posting as you do for a flow so the forum doesn't mess with it.
Also check in the browser Developer Console to see if there are any errors.

Yes it still appears in the menu.
I have no output from the ui_control node even if I select an output type.
I'm working with Raspberry Pi4.

You are right, I have an error in the browser console :

app.min.js:594 Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
    at D (app.min.js:594)
    at app.min.js:594
    at r.t (app.min.js:595)
    at r.emit (index.js:83)
    at r.onevent (index.js:83)
    at r.onpacket (index.js:83)
    at r.<anonymous> (index.js:83)
    at r.emit (index.js:83)
    at r.ondecoded (index.js:83)
    at a.<anonymous> (index.js:83)

I tried to have a look in app.min.js but I didn't really understand.
As it is about lower case I tried use mytab as tab name but it didn't help.

And my starting logs :

5 Oct 13:35:43 - [info] 

Welcome to Node-RED
===================

5 Oct 13:35:43 - [info] Node-RED version: v1.1.3
5 Oct 13:35:43 - [info] Node.js  version: v12.16.2
5 Oct 13:35:43 - [info] Linux 4.19.97-v7l+ arm LE
5 Oct 13:35:43 - [info] Loading palette nodes
5 Oct 13:35:45 - [info] Dashboard up and running
5 Oct 13:35:46 - [info] Dashboard version 2.23.4 started at /ui
5 Oct 13:35:46 - [info] Settings file  : /home/pi/.node-red/settings.js
5 Oct 13:35:46 - [info] Context store  : 'default' [module=memory]
5 Oct 13:35:46 - [info] User directory : /home/pi/.node-red
5 Oct 13:35:46 - [info] Server now running at http://127.0.0.1:1880/
5 Oct 13:35:46 - [info] Active project : Pibox-nodered
5 Oct 13:35:46 - [info] Flows file     : /home/pi/.node-red/projects/Pibox-nodered/flows.json
5 Oct 13:35:47 - [info] Starting flows
5 Oct 13:35:50 - [info] Started flows
5 Oct 13:35:50 - [info] serial port /dev/usb_2 opened at 1200 baud 8N1
5 Oct 13:35:50 - [info] serial port /dev/usb_1 opened at 9600 baud 7E1

I am out of ideas here, anyone else any suggestions?

Is there any other odd or weird things going on with the video presentation of the Pi4? Just covering basic ground work, ruling out stuff. When stuck like this, it often is logical to toss out all the assumptions and just start with nothing and working the issue again.

Is the behavior consistent across Microsoft Edge, Chrome, FireFox, etc? I have seen a few quirks between browsers at times with NR... not usually NR issue, but browser specific stuff.

Radical, but does the issue survive at clean boot image or OS installation and clean NR installation?

Does the issue survive a clean flows file, i.e. empty flows file, and only add the specific flow?

Again, this is not to second guess anything done thus far, but to literally avoid assumptions.

Since this worked in a previous version, the only core assumption is that something (as yet not qualified) has actually changed at some point during the most recent update. So, starting with a baseline of a know working setup and very careful selection of incremental updates, in lock step, is called for. This means checking every single module update from known good right?

Hi,
It is working properly on a clean project, and even with a previous version of my project, so it is definitely not an issue with the upgrade.
I don't understand what changed and I don't understand the error I have on the browser.
Do you know where it could come from ?

The error :

app.min.js:594 Uncaught TypeError: Cannot read property 'toLowerCase' of undefined
    at D (app.min.js:594)
    at app.min.js:594
    at r.t (app.min.js:595)
    at r.emit (index.js:83)
    at r.onevent (index.js:83)
    at r.onpacket (index.js:83)
    at r.<anonymous> (index.js:83)
    at r.emit (index.js:83)
    at r.ondecoded (index.js:83)
    at a.<anonymous> (index.js:83)

The app.min.js line 594, sorry it's fat but there are only 2 places with toLowerCase :

"function"!=typeof Object.assign&&(Object.assign=function(e){"use strict";if(null==e)throw new TypeError("Cannot convert undefined or null to object");for(var t=Object(e),n=1;n<arguments.length;n++){var a=arguments[n];if(null!=a)for(var o in a)a.hasOwnProperty(o)&&(t[o]=a[o])}return t}),String.prototype.startsWith||(String.prototype.startsWith=function(e,t){return t=t||0,this.indexOf(e,t)===t});var doVisualUpdates=!0;document.addEventListener("visibilitychange",function(){setTimeout(function(){doVisualUpdates=!document.hidden},1e3)});var dateFormat,app=angular.module("ui",["ngMaterial","ngMdIcons","ngSanitize","ngTouch","sprintf","chart.js","color.picker"]),locale=navigator.languages&&navigator.languages.length?navigator.languages[0]:navigator.language;moment.locale(locale),app.config(["$mdThemingProvider","$compileProvider","$mdDateLocaleProvider","$provide",function(e,t,n,a){e.generateThemesOnDemand(!0),a.value("themeProvider",e),t.aHrefSanitizationWhitelist(/.*/),n.months=moment.localeData().months(),n.shortMonths=moment.localeData().monthsShort(),n.days=moment.localeData().weekdays(),n.shortDays=moment.localeData().weekdaysMin(),n.formatDate=function(e){return e?moment(e).format(dateFormat||"DD MMM YYYY"):null},n.parseDate=function(e){var t=moment(e,dateFormat||"DD MMM YYYY",!0);return t.isValid()?t.toDate():new Date(NaN)},n.monthHeaderFormatter=function(e){return moment(e).format("MMM YYYY")}}]),app.controller("MainController",["$mdSidenav","$window","UiEvents","$location","$document","$mdToast","$mdDialog","$rootScope","$sce","$timeout","$scope","themeProvider","$mdTheming",function(n,a,m,l,s,d,i,u,r,c,h,p,g){this.menu=[],this.headElementsAppended=[],this.headOriginalElements=[],this.len=0,this.selectedTab=null,this.loaded=!1,this.hideToolbar=!1,this.allowSwipe=!1,this.lockMenu=!1,this.allowTempTheme=!0;var f,w,b=this,v=[],y=0,T=!0;function S(e){var t=b.menu.length;if(1<t)for(var n=+y+e;n!=y;n+=e)if((n%=t)<0&&(n+=t),!b.menu[n].disabled&&!b.menu[n].hidden)return b.select(n),void(y=n)}function O(e){for(var t=Object.keys(e.themeState),n={},a=0;a<t.length;a++){for(var o=t[a].split("-"),i=1;i<o.length;i++)o[i]=o[i].charAt(0).toUpperCase()+o[i].slice(1);var r=o.join(""),l=e.themeState[t[a]].value;n["@"+r]=l}void 0===b.allowTempTheme&&(b.allowTempTheme=!0),n["@nrTemplateTheme"]=b.allowTempTheme,n["@nrTheme"]=!b.allowAngularTheme,n["@nrUnitHeight"]=b.sizes.sy/2+"px",less.modifyVars(n)}function k(e){var t=s.find("head").find(e.expression)[0];angular.element(t).replaceWith(e.html)}function P(e){var t=s.find("head").children();e.childrenIndex.forEach(function(e){t.hasOwnProperty(e)&&t[e].parentNode.removeChild(t[e])})}function I(a,o){var i=s.find("head"),e=i.children().length,r=angular.element("<head></head>");r.append(o);if(["meta[charset]",'meta[name="viewport"]','meta[name="apple-mobile-web-app-capable"]','meta[name="apple-mobile-web-app-status-bar-style"]','meta[name="apple-mobile-web-app-title"]','meta[name="mobile-web-app-capable"]','link[rel="icon"]','link[rel="shortcut icon"]','link[rel="apple-touch-icon"]'].forEach(function(e){var t=r.find(e);if(0<t.length){var n=i.find(e)[0];b.headOriginalElements.push({id:a,expression:e,html:n}),angular.element(n).replaceWith(t[0]),(o=r.html()).trim()}}),""!==o){i.append(o);for(var t=[],n=e;n<i.children().length;n++)t.push(n);e=i.children().length,b.headElementsAppended.push({id:a,childrenIndex:t})}}function C(e,t){for(var n=0;n<t.length;n++){var a=t[n];if(a.id===e)return a;if(a.items){var o=C(e,a.items);if(o)return o}}}function D(e,t){var n=e&&Array.isArray(e)?e:[e];return(n=n.map(function(e){return e.toLowerCase().replace(/\s+/g,"_")})).includes(t.toLowerCase().replace(/\s+/g,"_"))}h.onSwipeLeft=function(){b.allowSwipe&&S(-1)},h.onSwipeRight=function(){b.allowSwipe&&S(1)},h.$on("$locationChangeSuccess",function(e,t,n,a,o){if(l.path()!=="/"+y){var i=parseInt(l.path().split("/")[1],10);if(!isNaN(i)){var r=b.menu[i];r&&b.open(r,i)}}}),u.$on("collapse",function(e,t,n){m.emit("ui-collapse",{group:t,state:n})}),this.toggleSidenav=function(){n("left").toggle()},this.select=function(e){b.selectedTab=b.menu[e],0<b.menu.length&&n("left")&&n("left").close(),y=e,m.emit("ui-change",y),l.path(e)},this.open=function(e,t){void 0===e.link?this.select(t):("newtab"===e.target?a.open(e.link,e.name):"thistab"===e.target?a.open(e.link,"_self"):("string"==typeof b.menu[t].link&&(b.menu[t].link=r.trustAsResourceUrl(b.menu[t].link)),b.select(t)),n("left").close())},h.location=l,this.getMenuName=function(e){return void 0!==e.link?e.name:e.header},m.connect(function(e,t){var n;T=!1,m.emit("ui-params",l.search()),b.menu=e.menu,b.globals=e.globals,b.nothing=!1,e.site&&(n=b.name=e.site.name,b.hideToolbar="true"==e.site.hideToolbar,b.allowSwipe="true"==e.site.allowSwipe,b.lockMenu="true"==e.site.lockMenu,void 0===e.site.allowTempTheme?b.allowTempTheme=!0:(b.allowTempTheme="true"==e.site.allowTempTheme,b.allowAngularTheme="none"==e.site.allowTempTheme),dateFormat=e.site.dateFormat||"DD/MM/YYYY",e.site.hasOwnProperty("sizes")&&(sizes.setSizes(e.site.sizes),b.sizes=e.site.sizes)),e.theme&&e.theme.angularTheme&&(p.theme("default").primaryPalette(e.theme.angularTheme.primary||"indigo").accentPalette(e.theme.angularTheme.accents||"blue").warnPalette(e.theme.angularTheme.warn||"red").backgroundPalette(e.theme.angularTheme.background||"grey"),"dark"===e.theme.angularTheme.palette&&p.theme("default").dark(),g.generateTheme("default")),s[0].theme=e.theme,e.title&&(n=e.title),s[0].title=n||"Node-RED Dashboard",$("meta[name=apple-mobile-web-app-title]").attr("content",n||"Node-RED");var a=parseInt(l.path().substr(1));"speechSynthesis"in window&&(v=window.speechSynthesis.getVoices(),window.speechSynthesis.onvoiceschanged=function(){v=window.speechSynthesis.getVoices()});var o=function(){b.selectedTab&&"object"==typeof b.selectedTab.theme?(b.selectedTab.theme.themeState["widget-borderColor"]=b.selectedTab.theme.themeState["widget-borderColor"]||b.selectedTab.theme.themeState["group-backgroundColor"],O(b.selectedTab.theme)):"object"==typeof e.theme&&e.theme.themeState["base-color"].value&&O(e.theme),null!==b.selectedTab&&void 0!==b.selectedTab.link&&(b.selectedTab.link=r.trustAsResourceUrl(b.selectedTab.link)),e.hasOwnProperty("theme")?$("meta[name=theme-color]").attr("content",e.theme.themeState["page-titlebar-backgroundColor"].value||"#097479"):$("meta[name=theme-color]").attr("content","#097479"),d.hide(),b.headElementsAppended.forEach(function(e){P(e)}),b.headElementsAppended=[],b.headOriginalElements.forEach(function(e){k(e)}),0<b.globals.length&&b.globals.forEach(function(e){void 0!==e.format&&""!==e.format&&I(e.id,e.format)}),m.emit("ui-change",a),function(){var e=!1;for(var t in b.menu)if(b.menu.hasOwnProperty(t))for(var n in"undefined"!=typeof localStorage&&("true"==localStorage.getItem("th"+t+b.menu[t].header)&&(!0===b.menu[t].hidden?localStorage.removeItem("th"+t+b.menu[t].header):b.menu[t].hidden=!0,e=!0),"false"==localStorage.getItem("th"+t+b.menu[t].header)&&(!1===b.menu[t].hidden?localStorage.removeItem("th"+t+b.menu[t].header):b.menu[t].hidden=!1,e=!0),"true"==localStorage.getItem("td"+t+b.menu[t].header)&&(!0===b.menu[t].disabled?localStorage.removeItem("td"+t+b.menu[t].header):b.menu[t].disabled=!0,e=!0),"false"==localStorage.getItem("td"+t+b.menu[t].header)&&(!1===b.menu[t].disabled?localStorage.removeItem("td"+t+b.menu[t].header):b.menu[t].disabled=!1,e=!0)),b.menu[t].items)if(b.menu[t].items.hasOwnProperty(n)){var a=(b.menu[t].header+" "+b.menu[t].items[n].header.name).replace(/ /g,"_");"undefined"!=typeof localStorage&&"true"==localStorage.getItem("g"+a)&&(e=b.menu[t].items[n].header.config.hidden=!0)}!0===e&&$(window).trigger("resize")}(),t()};!isNaN(a)&&a<b.menu.length&&!b.menu[a].disabled?(b.selectedTab=b.menu[a],o()):c(function(){var n=null;b.menu.some(function(e,t){if(void 0===e.target||"iframe"===e.target)return!e.disabled&&(n=t,!0)}),null!==n?(b.open(b.menu[n],n),o()):b.nothing=!0},50),b.len=b.menu.length},function(){b.loaded=!0,h.$apply()}),m.on(function(e){var t,n,a,o,i,r,l;if(e.hasOwnProperty("msg")&&"global"===e.msg.templateScope)if(r=e.id,l=!1,b.headOriginalElements.some(function(e){if(e.id===r)return l=e,!0}),t=l)o=t,i=e.msg.template,k(o),I(o.id,i);else{if(n=e.id,a=!1,b.headElementsAppended.some(function(e){if(e.id===n)return a=e,!0}),!(t=a))return;!function(e,t){P(e);var n=b.headElementsAppended.indexOf(e);0<=n&&b.headElementsAppended.splice(n,1),I(e.id,t)}(t,e.msg.template)}else{if(void 0===(t=C(e.id,b.menu)))return;for(var s in e)if(e.hasOwnProperty(s)){if("id"===s)continue;t[s]=e[s]}t.hasOwnProperty("me")&&t.me.hasOwnProperty("processInput")&&t.me.processInput(e)}h.$apply()}),m.on("disconnect",function(e){!T&&doVisualUpdates&&(d.show({template:'<md-toast><div class="md-toast-error">&#x2718; &nbsp; Connection lost</div></md-toast>',position:"top right",hideDelay:6e6}),T=!0)}),m.on("connect_error",function(e){"TransportError"===e.type&&401===e.description&&function(){if(!((new Date).getTime()-1*((e=window.location.search.match(/[?&]random=([^&]*)/))&&e[1]||0)<6e4)){var e,t=window.location.search;(t=t.replace(/[?&]random=([^&]*)/,"")).startsWith("?")||(t="?"+t),t+="&random="+(new Date).getTime();var n=window.location.origin;n+=window.location.pathname,n+=t,n+=window.location.hash,window.location=n}}()}),m.on("show-toast",function(t){if(!0!==t.raw){var e=document.createElement("div");e.textContent=t.message,t.message=e.innerHTML}if(!0===t.dialog){var n;if(""==t.message)return void i.cancel();t.cancel&&t.prompt?(n=i.prompt().title(t.title).htmlContent(t.message).initialValue("").ariaLabel(t.ok+" or "+t.cancel).ok(t.ok).cancel(t.cancel))._options.focusOnOpen=!1:t.cancel?(n=i.confirm().title(t.title).htmlContent(t.message).ariaLabel(t.ok+" or "+t.cancel).ok(t.ok).cancel(t.cancel))._options.focusOnOpen=!1:n=i.alert().title(t.title).htmlContent(t.message).ariaLabel(t.ok).ok(t.ok),n._options.template='<md-dialog md-theme="{{ dialog.theme || dialog.defaultTheme }}" aria-label="{{ dialog.ariaLabel }}" ><md-dialog-content class="md-dialog-content" role="document" tabIndex="-1"><h2 class="md-title">{{ dialog.title }}</h2><div ng-if="::dialog.mdHtmlContent" class="md-dialog-content-body"ng-bind-html="::dialog.mdHtmlContent | trusted"></div><div ng-if="::!dialog.mdHtmlContent" class="md-dialog-content-body"><p>{{::dialog.mdTextContent}}</p></div><md-input-container md-no-float ng-if="::dialog.$type == \'prompt\'" class="md-prompt-input-container"><input ng-keypress="dialog.keypress($event)" md-autofocus ng-model="dialog.result"placeholder="{{::dialog.placeholder}}" ng-required="dialog.required"></md-input-container></md-dialog-content><md-dialog-actions><md-button ng-if="dialog.$type === \'confirm\' || dialog.$type === \'prompt\'"ng-click="dialog.abort()" class="md-primary md-cancel-button">{{ dialog.cancel }}</md-button><md-button ng-click="dialog.hide()" class="md-primary md-confirm-button" md-autofocus="dialog.$type===\'alert\'" ng-disabled="dialog.required && !dialog.result">{{ dialog.ok }}</md-button></md-dialog-actions></md-dialog>',i.show(n,{panelClass:"nr-dashboard-dialog"}).then(function(e){console.log("RES",typeof e,e,"::",t.ok,"::"),t.msg.payload=t.ok,1!=e&&(t.msg.payload=e),null==e&&(t.msg.payload=""),console.log("MSG",t),m.emit({id:t.id,value:t})},function(){t.msg.payload=t.cancel,m.emit({id:t.id,value:t})})}else if(t.hasOwnProperty("message")||t.hasOwnProperty("title")){var a=u.$new();(a.toast=t).hasOwnProperty("message")&&""==t.message&&(t.displayTime=1);var o={scope:a,templateUrl:"partials/toast.html",hideDelay:t.displayTime,position:t.position};d.show(o)}}),m.on("ui-control",function(e){if(!e.hasOwnProperty("socketid")||e.socketid===m.id){if(e.hasOwnProperty("control")){var t=C(e.id,b.menu);for(var n in e.control)e.control.hasOwnProperty(n)&&t.hasOwnProperty(n)&&(t[n]=e.control[n])}if(e.hasOwnProperty("tabs")&&"object"==typeof e.tabs)for(var a in b.menu)b.menu.hasOwnProperty(a)&&(e.tabs.hasOwnProperty("show")&&D(e.tabs.show,b.menu[a].header)&&(b.menu[a].hidden=!1,localStorage.setItem("th"+a+b.menu[a].header,!1)),e.tabs.hasOwnProperty("hide")&&D(e.tabs.hide,b.menu[a].header)&&(b.menu[a].hidden=!0,localStorage.setItem("th"+a+b.menu[a].header,!0)),e.tabs.hasOwnProperty("enable")&&D(e.tabs.enable,b.menu[a].header)&&(b.menu[a].disabled=!1,localStorage.setItem("td"+a+b.menu[a].header,!1)),e.tabs.hasOwnProperty("disable")&&D(e.tabs.disable,b.menu[a].header)&&(b.menu[a].disabled=!0,localStorage.setItem("td"+a+b.menu[a].header,!0)));if(e.hasOwnProperty("tab")){if("string"==typeof e.tab){if(""===e.tab&&m.emit("ui-refresh",{}),"+1"===e.tab)return S(1),void h.$apply();if("-1"===e.tab)return S(-1),void h.$apply();for(var o in b.menu){if(e.tab==b.menu[o].header)return b.menu[o].disabled||b.select(o),void h.$apply();if(e.tab==b.menu[o].name)return b.menu[o].disabled||b.open(b.menu[o],o),void h.$apply()}}var i=parseInt(e.tab);if(Number.isNaN(i)||i<0)return;if(i<b.menu.length)return b.menu[i].disabled||b.open(b.menu[i],i),void h.$apply()}if(e.hasOwnProperty("group")&&"object"==typeof e.group)for(var r in b.menu)if(b.menu.hasOwnProperty(r)){var l;for(var s in b.menu[r].items)if(b.menu[r].items.hasOwnProperty(s)){var d=(b.menu[r].header+" "+b.menu[r].items[s].header.name).replace(/ /g,"_");e.group.hasOwnProperty("show")&&-1<e.group.show.indexOf(d)&&(b.menu[r].items[s].header.config.hidden=void 0,localStorage.removeItem("g"+d),l=d),e.group.hasOwnProperty("hide")&&-1<e.group.hide.indexOf(d)&&(b.menu[r].items[s].header.config.hidden=!0,localStorage.setItem("g"+d,!0)),e.group.hasOwnProperty("close")&&-1<e.group.close.indexOf(d)&&"undefined"!=typeof localStorage&&"false"==localStorage.getItem(d)&&$("#"+d+" > div > p > span > i").trigger("click"),e.group.hasOwnProperty("open")&&-1<e.group.open.indexOf(d)&&"undefined"!=typeof localStorage&&"true"==localStorage.getItem(d)&&$("#"+d+" > div > p > span > i").trigger("click"),$(window).trigger("resize")}e.group.hasOwnProperty("focus")&&l&&setTimeout(function(){(l=$(window)[0].document.getElementById(l))&&l.scrollIntoView()},50)}h.$apply()}}),m.on("ui-audio",function(e){if(e.reset)w?(w.disconnect(),w.stop(0),w=null,m.emit("ui-audio","reset")):window.speechSynthesis.speaking&&(window.speechSynthesis.cancel(),m.emit("ui-audio","reset"));else{if(!e.always){var t;for(var n in b.menu)e.tabname===b.menu[n].header&&(t=n);if(t!=parseInt(l.path().substr(1)))return}if(e.hasOwnProperty("tts"))if(0<v.length){var a=new SpeechSynthesisUtterance(e.tts);a.onerror=function(e){m.emit("ui-audio","error: "+e.error)},a.onend=function(){m.emit("ui-audio","complete")};for(var o=0;o<v.length;o++)if(v[o].voiceURI===e.voice){a.voice=v[o];break}m.emit("ui-audio","playing"),window.speechSynthesis.speak(a)}else{console.log("This Browser does not support Text-to-Speech");var i=u.$new();i.toast={message:e.tts,title:"Computer says..."},d.show({scope:i,position:"top right",templateUrl:"partials/toast.html"})}if(e.hasOwnProperty("audio")){window.hasOwnProperty("AudioContext")||(window.AudioContext=window.AudioContext||window.webkitAudioContext||window.mozAudioContext);try{f=f||new AudioContext,(w=f.createBufferSource()).onended=function(){m.emit("ui-audio","complete")};var r=new Uint8Array(e.audio);f.decodeAudioData(r.buffer,function(e){w.buffer=e,w.connect(f.destination),w.start(0),m.emit("ui-audio","playing")},function(){m.emit("ui-audio","error")})}catch(e){m.emit("ui-audio","error")}}}})}]);

Thanks

Step through the flow step by step with debug nodes... The undefined reference means that something is not set right (i.e. variable value is never set, or variable never created). The function is not returning acceptable value for example?

Unfortunately for some reason I cannot import the flow you posted. The import is rejecting it as an invalid JSON array.

The undefined is not in the flow but in the app.min.js

The flow won't be helpful as it works properly on a new project. I don't understand what's wrong on my project and prevent ui_control to have the right behaviour.

Ah, ok, so then it should be a bit easier to debug... if you are familiar with JavaScript? The issue is still applicable of course, undefined variable.

I know a bit of JS but for the app.min.js it's another level to understand...

I was wondering if any of my code inside nodered has an impact on this file, do you know if it's the case ?

Different environments, node.js as run say from the console stages differently than when JavaScript is run within a NR function node.

When the code is run in node.js or native JavaScript environment, it works right? But if you try to run the code in NR in a function node? That is when it fails? This would be the first step to finding the issue(s).

I am just trying to understand where or when the code works versus not. Unfortunately, I can't run the code you posted in node.js it self. It is not a complete script or solution?

ReferenceError: document is not defined
    at Object.<anonymous> (/root/test.js:1:422)
    at Module._compile (internal/modules/cjs/loader.js:1015:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1035:10)
    at Module.load (internal/modules/cjs/loader.js:879:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js                                                        :60:12)
    at internal/main/run_main_module.js:17:47

I found this error is coming from a link I added to my dashboard layout (where you can manage your tabs).
When I remove this link the ui_control is working properly, I don't know why.

Well, color me confused... odd. So whatever was not getting set is not being set... no more undefined reference. But even that might have been misleading given you really did not change any 'code' per se.

Can you publish the entire flow? Just so I see how the entire flow is implemented?