# Problem sending message from ui-template node

**URL:** <https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469>\
**Category:** Dashboard\
**Tags:** node-red-dashboard\
**Created:** [29 January 2022 21:12 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469 "2022-01-29T21:12:01Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jdo300](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jdo300/32/79415_2.png) [@Jdo300](https://discourse.nodered.org/u/Jdo300)\
**Post date:** [29 January 2022 21:12 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/1 "2022-01-29T21:12:01Z")

</div>

I created a ui-template node for my dashboard containing some code to create a clock with a clickable Home icon on the upper-right corner of my dashboard. The node is being added to the site header. The clock and Home icons display just fine but I"m having trouble making the home icon send you back to the homepage when clicked. In my code, I am able to fire off an event when the icon is clicked, but I get an error saying that `send({payload:"Home"}) function is not defined`. here's the code for the template node below:

```auto
<script type="text/javascript">
    var theScope = null;

    $(function(scope)
    {
        theScope = scope;
        if($('.md-toolbar-tools').length != 0)
            loadClock();
        else 
            setTimeout(loadClock, 500);
    });
    
    function loadClock(){
        $('#clock').remove();
        var toolbar = $('.md-toolbar-tools');
        
        var div = $('<div/ class="clock-style">');
        var p = $('<p/ id="clock">');
        
        div.append(p);
        div[0].style.margin = '5px 5px 5px auto';
        toolbar.append(div);
        
        // Add element for clickable home icon if not already present
        var i = document.createElement('i');
        i.classList.add("fa");
        i.classList.add("fa-home");
        i.classList.add("fa-2x");
        i.classList.add("icon-padding");
        i.addEventListener('click', sendPayload);
        toolbar.append(i);
        
        function displayTitle(lh) {
            p.text(lh); 
        }
        
        function upTime() {
            var d = new Date();
            p.text(d.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'}));
        }
    
        if(document.clockInterval){ 
            clearInterval(document.clockInterval);
            document.clockInterval = null;
        }
            
        document.clockInterval = setInterval(upTime, 1000);
    
        function sendPayload(){
            theScope.send({payload:"Home"});
        }
    }
</script>

```

Any idea what I'm doing wrong? I just want to send a message to the UI node to change the dashboard page.

**NOTE** : Above code edited to include missing assignment statement for the `theScope` variable inside of the main function.

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [29 January 2022 23:01 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/2 "2022-01-29T23:01:50Z")

</div>

Hello ..

Why do you set the `theScope` to `null` ?  
set it to ` var theScope = scope;`  
so you can have access to the `send` method

---

<div class="post-metadata">

**Author:** ![Jdo300](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jdo300/32/79415_2.png) [@Jdo300](https://discourse.nodered.org/u/Jdo300)\
**Post date:** [30 January 2022 18:40 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/3 "2022-01-30T18:40:28Z")

</div>

Actually, the original rendition of this code had `theScope = scope;` at the top. But when running the dashboard page, I get an error saying `'scope is not defined.'` So after looking around at some other examples, I noticed that some showed the scope variable being passed in from the anonymous main function that gets called when the script first runs, so I included it there and assigned `theScope = scope;` inside this function (By the way, I forgot to include that change in the code I posted earlier. It is included now).

But this time, I get an error saying, "`theScope.send is not a function`"

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [30 January 2022 18:57 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/4 "2022-01-30T18:57:39Z")

</div>

Use the self calling Function as the example in the Help tab of the ui\_template  
that passes scope so it can be accessed anywhere in the code.  
then use it as ` scope.send({ payload: "Home" });`

> **ui\_template Code**
>
> ```auto
> <script type="text/javascript">
> 
> (function (scope) {
> 
> if ($('.md-toolbar-tools').length != 0)
> loadClock();
> else
> setTimeout(loadClock, 500);
> 
> function loadClock() {
> $('#clock').remove();
> var toolbar = $('.md-toolbar-tools');
> 
> var div = $('<div/ class="clock-style">');
> var p = $('<p/ id="clock">');
> 
> div.append(p);
> div[0].style.margin = '5px 5px 5px auto';
> toolbar.append(div);
> 
> // Add element for clickable home icon if not already present
> var i = document.createElement('i');
> i.classList.add("fa");
> i.classList.add("fa-home");
> i.classList.add("fa-2x");
> i.classList.add("icon-padding");
> i.addEventListener('click', sendPayload);
> toolbar.append(i);
> 
> function displayTitle(lh) {
> p.text(lh);
> }
> 
> function upTime() {
> var d = new Date();
> p.text(d.toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }));
> }
> 
> if (document.clockInterval) {
> clearInterval(document.clockInterval);
> document.clockInterval = null;
> }
> 
> document.clockInterval = setInterval(upTime, 1000);
> 
> function sendPayload() {
> scope.send({ payload: "Home" });
> }
> }
> 
> })(scope);
> 
> </script>
> 
> ```

---

<div class="post-metadata">

**Author:** ![Jdo300](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jdo300/32/79415_2.png) [@Jdo300](https://discourse.nodered.org/u/Jdo300)\
**Post date:** [2 February 2022 15:40 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/5 "2022-02-02T15:40:30Z")

</div>

Hello, I'm still struggling to get this to work (no idea what I'm still doing wrong). Here's the latest code I have been testing

```auto
[{"id":"0c14a683067f1149","type":"ui_template","z":"a084448f7f5e471e","group":"c982fbb8.1deb38","name":"Global Styles","order":2,"width":"0","height":"0","format":"<script type=\"text/javascript\">\n $(function(scope)\n {\n if($('.md-toolbar-tools').length != 0)\n loadClock();\n else \n setTimeout(loadClock, 500);\n \n function sendPayload(){\n scope.send({payload:\"Home\"});\n }\n \n function loadClock(){\n $('#clock').remove();\n var toolbar = $('.md-toolbar-tools');\n \n var div = $('<div/ class=\"clock-style\">');\n var p = $('<p/ id=\"clock\">');\n \n div.append(p);\n div[0].style.margin = '5px 5px 5px auto';\n toolbar.append(div);\n \n // Add element for clickable home icon if not already present\n var i = document.createElement('i');\n i.classList.add(\"fa\");\n i.classList.add(\"fa-home\");\n i.classList.add(\"fa-2x\");\n i.classList.add(\"icon-padding\");\n i.addEventListener('click', sendPayload);\n toolbar.append(i);\n \n function displayTitle(lh) {\n p.text(lh); \n }\n \n function upTime() {\n var d = new Date();\n p.text(d.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'}));\n }\n \n if(document.clockInterval){ \n clearInterval(document.clockInterval);\n document.clockInterval = null;\n }\n \n document.clockInterval = setInterval(upTime, 1000);\n }\n });\n</script>\n","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":false,"templateScope":"global","className":"","x":130,"y":200,"wires":[["fd314f635fc03051"]]},{"id":"fd314f635fc03051","type":"ui_ui_control","z":"a084448f7f5e471e","name":"","events":"all","x":360,"y":200,"wires":[[]]},{"id":"c982fbb8.1deb38","type":"ui_group","name":"hidden_group","tab":"7c447e96.4b96a","order":1,"disp":false,"width":"6","collapse":false},{"id":"7c447e96.4b96a","type":"ui_tab","name":"Zooland Sys","icon":"home","order":36,"disabled":false,"hidden":true}]

```

and Here is the full code for the template node I made:

```auto
<script type="text/javascript">
    $(function(scope)
    {
        if($('.md-toolbar-tools').length != 0)
            loadClock();
        else 
            setTimeout(loadClock, 500);
        
        function sendPayload(){
            scope.send({payload:"Home"});
        }
    
        function loadClock(){
            $('#clock').remove();
            var toolbar = $('.md-toolbar-tools');
            
            var div = $('<div/ class="clock-style">');
            var p = $('<p/ id="clock">');
            
            div.append(p);
            div[0].style.margin = '5px 5px 5px auto';
            toolbar.append(div);
            
            // Add element for clickable home icon if not already present
            var i = document.createElement('i');
            i.classList.add("fa");
            i.classList.add("fa-home");
            i.classList.add("fa-2x");
            i.classList.add("icon-padding");
            i.addEventListener('click', sendPayload);
            toolbar.append(i);
            
            function displayTitle(lh) {
                p.text(lh); 
            }
            
            function upTime() {
                var d = new Date();
                p.text(d.toLocaleTimeString([], {hour: 'numeric', minute:'2-digit'}));
            }
        
            if(document.clockInterval){ 
                clearInterval(document.clockInterval);
                document.clockInterval = null;
            }
                
            document.clockInterval = setInterval(upTime, 1000);
        }
    });
</script>

```

When running this on a blank page, the clock and Home icon appear as they should, but wen clicking on the home icon, the error I get in the Java console is:

```auto
VM36:10 Uncaught TypeError: scope.send is not a function
    at HTMLElement.sendPayload (<anonymous>:10:19)

```

I'm sure there is something simple I'm still missing but I think I've been staring at it too long to see it...

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [2 February 2022 15:47 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/6 "2022-02-02T15:47:39Z")

</div>

hello .. you didnt use in your code a self calling function and pass `scope` in  
(see the example i sent you in the last post)

```auto
 (function (scope) {

  ....

    })(scope);

```

---

<div class="post-metadata">

**Author:** ![Jdo300](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jdo300/32/79415_2.png) [@Jdo300](https://discourse.nodered.org/u/Jdo300)\
**Post date:** [4 February 2022 14:13 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/7 "2022-02-04T14:13:16Z")

</div>

Hi @UnborN. Yes, I did miss that small detail (adding scope at the end of the self-calling function. I did two tests, in the first, I took the code as-is from your example, placed it in the global template node and ran it. Once the dashboard launched, I got this error:

```auto
Uncaught ReferenceError: scope is not defined
    at <anonymous>:52:8
    at b (app.min.js:20:866)
    at He (app.min.js:20:48373)
    at S.fn.init.append (app.min.js:20:49724)
    at D (app.min.js:589:4330)
    at app.min.js:589:7887
    at Array.forEach (<anonymous>)
    at o (app.min.js:589:7833)
    at app.min.js:589:9033
    at Socket.<anonymous> (app.min.js:590:462)

```

Could the fact that the ui-template node is being added to the site head section rather than a dashboard group make a difference? It really seems to be having issues getting the scope reference.

Also, is there a simpler way to accomplish this? All I want to do is make the home icon go back to the home page when clicked. Is there a way to just link to the home page through a URL?

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [4 February 2022 14:19 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/8 "2022-02-04T14:19:25Z")

</div>

> [@Jdo300](#):
>
> Also, is there a simpler way to accomplish this?

yes .. dont add it to the head 😉  
i missed that part (you did mention it)

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/e/b/eb11cc6651fc61fa15c00ac64cbb6f325a3b4fa3.png)

---

<div class="post-metadata">

**Author:** ![Jdo300](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/jdo300/32/79415_2.png) [@Jdo300](https://discourse.nodered.org/u/Jdo300)\
**Post date:** [4 February 2022 15:16 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/9 "2022-02-04T15:16:22Z")

</div>

Haha ok. I assigned the template node to one of the UI-groups and yes it works now. But in this way, I would need to make a copy of this node to go on every page of the dashboard for it to work. I can do that if necessary, but are there any better approaches to do the same thing?

I was looking at the code for the Nav menu to see how it is being linked to the home page when clicked. It looks like the click event of the menu items point to a function like this: `ng-click="main.open(obj, $index)"`. I'm not sure if this could somehow be adapted to work with my template node but this is something I am considering as an alternative.

The last idea is I noticed that the URL for the dashboard pages seem to follow an index number format: `/ui/#!/0, /ui/#!/1` etc. If my homepage happens to be index 0, is it safe to assume that it will always be 0? Is the index determined by the order that the dashboard tabs are sorted in the Tabs and Links list?

---

<div class="post-metadata">

**Author:** ![UnborN](https://avatars.discourse-cdn.com/v4/letter/u/4491bb/32.png) [@UnborN](https://discourse.nodered.org/u/UnborN)\
**Post date:** [4 February 2022 15:53 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/10 "2022-02-04T15:53:49Z")

</div>

> [@Jdo300](#):
>
> But in this way, I would need to make a copy of this node to go on every page of the dashboard for it to work

It seems like it .. i did a quick test also and the Tabs dont load until you select them from the sidebar.  
If you add the code to the `<head>` then no access to `scope`.

Interesting finding you did about the inner workings of the Dashboard but without a way to manipulate that code i think we are stack to adding a hidden template to each Tab .. and also add code to check if your html elements are already injected to the top navbar.

**Similar Thread here:**

> [@Bind text in the Dashboard header](https://discourse.nodered.org/t/bind-text-in-the-dashboard-header/23656/5):
>
> If you would like to see it in all dashboards tabs you could use my flow as a base, then place an hidden template node in all tabs (in template node options place it in the body and not in the head section because if in the head it cannot receive msg inputs) in that template just set up the template node to watch for the input: \<script\> (function(scope) { scope.$watch('msg.payload', function(data) { // get the element from the dashoard header and change its status using …

Or an alternative is to look into **[node-red-contrib-uibuilder](https://flows.nodered.org/node/node-red-contrib-uibuilder)**  
that gives you the flexibility to create your own dashboard from scratch with full access to your own code  
but that would require some knowledge of html, css, javascript or any front-end language

---

<div class="post-metadata">

**Author:** ![zenofmud](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/zenofmud/32/316_2.png) [@zenofmud](https://discourse.nodered.org/u/zenofmud)\
**Post date:** [4 February 2022 15:54 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/11 "2022-02-04T15:54:31Z")

</div>

> [@Jdo300](#):
>
> Is the index determined by the order that the dashboard tabs are sorted in the Tabs and Links list?

Yes as long as you don't reorder them. You can use ui-control with group/tab names. Here is site with some examples of ui-control

> **[Using the Control UI Node With Flow Example](https://stevesnoderedguide.com/using-control-ui-node-flow-example)**
>
> Learn how to use the control ui dashboard node to create dynamic menus by hiding groups.

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [6 March 2022 15:54 UTC](https://discourse.nodered.org/t/problem-sending-message-from-ui-template-node/57469/12 "2022-03-06T15:54:38Z")

</div>

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