# Add a script dynamically?

**URL:** <https://discourse.nodered.org/t/add-a-script-dynamically/61878>\
**Category:** Dashboard\
**Created:** [27 April 2022 15:47 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878 "2022-04-27T15:47:01Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![Sean-McG](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sean-mcg/32/54677_2.png) [@Sean-McG](https://discourse.nodered.org/u/Sean-McG)\
**Post date:** [27 April 2022 15:47 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/1 "2022-04-27T15:47:01Z")

</div>

So like many I have added some buttons etc to the header.

For these to work the required code needs to be added to the header, from a template in a group on every tab.

As the number of tabs grows, this makes maintaining the code difficult, as any changes need to be duplicated many times in each template.

So I thought it should be possible to save the code once and then just load it in each template.

I found some info about this on the web, and it does “seem” to load the script, but perhaps it is not running it, as none of the buttons etc are drawn on the header.

Has anyone got this working or have any pointers for me ?

```auto

<script>
  var headerscript = document.createElement('script');
  headerscript.setAttribute('type','text/javascript');
  headerscript.setAttribute('src','/home/pi/.node-red/public/myjs/header.js');
  headerscript.setAttribute('async', 'defer');
  document.body.appendChild(headerscript);
</script>

```

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [27 April 2022 16:02 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/2 "2022-04-27T16:02:48Z")

</div>

You could store in file or context and then use msg.template to load the template script from a normal template node or function or change.  
here is a very simplified example.

```auto
[{"id":"1af346df.7103f9","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":290,"y":140,"wires":[["7e3b5bc7.cbc43c"]]},{"id":"7e3b5bc7.cbc43c","type":"template","z":"bf9e1e33.030598","name":"","field":"template","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"<script>\n {{{flow.template_header_script}}}\n</script>","output":"str","x":470,"y":140,"wires":[["a4c28729.b95928"]]},{"id":"a4c28729.b95928","type":"ui_template","z":"bf9e1e33.030598","group":"8b5cde76.edd58","name":"","order":8,"width":0,"height":0,"format":"","storeOutMessages":true,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":650,"y":140,"wires":[[]]},{"id":"2650e6f5.4de6ca","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"alert(\"Hello! I am an alert box!!\")","payloadType":"str","x":120,"y":60,"wires":[["4c02e77d.95df48"]]},{"id":"4c02e77d.95df48","type":"change","z":"bf9e1e33.030598","name":"","rules":[{"t":"set","p":"template_header_script","pt":"flow","to":"payload","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":390,"y":60,"wires":[[]]},{"id":"8b5cde76.edd58","type":"ui_group","name":"default","tab":"8f03e639.85956","order":1,"disp":false,"width":"12","collapse":false},{"id":"8f03e639.85956","type":"ui_tab","name":"Home","icon":"dashboard","order":2,"disabled":false,"hidden":false}]

```

or simply load the script from an endpoint or static folder.

```auto
[{"id":"93d1e86d.a97468","type":"http in","z":"bf9e1e33.030598","name":"","url":"/js_script","method":"get","upload":false,"swaggerDoc":"","x":160,"y":80,"wires":[["d7fcbfff.286458"]]},{"id":"d7fcbfff.286458","type":"change","z":"bf9e1e33.030598","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"alert(\"an alert\")","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":260,"y":40,"wires":[["5fb30c14.5253fc"]]},{"id":"5fb30c14.5253fc","type":"http response","z":"bf9e1e33.030598","name":"","statusCode":"","headers":{},"x":410,"y":80,"wires":[]},{"id":"528140c6.f07058","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":140,"wires":[["a4c28729.b95928"]]},{"id":"a4c28729.b95928","type":"ui_template","z":"bf9e1e33.030598","group":"8b5cde76.edd58","name":"","order":8,"width":0,"height":0,"format":"<script type=\"text/javascript\" src=\"/js_script\"></script>","storeOutMessages":true,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":450,"y":140,"wires":[[]]},{"id":"8b5cde76.edd58","type":"ui_group","name":"default","tab":"8f03e639.85956","order":1,"disp":false,"width":"12","collapse":false},{"id":"8f03e639.85956","type":"ui_tab","name":"Home","icon":"dashboard","order":2,"disabled":false,"hidden":false}]

```

---

<div class="post-metadata">

**Author:** ![Sean-McG](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sean-mcg/32/54677_2.png) [@Sean-McG](https://discourse.nodered.org/u/Sean-McG)\
**Post date:** [27 April 2022 16:54 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/3 "2022-04-27T16:54:37Z")

</div>

Thanks -

This only seems to run the script once at the inject - it needs the script to be added to the page as it listens for msgs.

If I send the messages to the template node nothing happens (as it an empty template, after the injected  
script)

Hope that makes sense ?

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [27 April 2022 17:01 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/4 "2022-04-27T17:01:56Z")

</div>

> [@Sean-McG](#):
>
> `'src','/home/pi/.node-red/public/myjs/header.js'`

That is not a URL, it is a filing system path. The Dashboard runs in the context of the browser, any nodes run in the context of the Node-RED server. These are completely different environments, often on completely different devices.

Also, depending on where you added that code, it will change when the script is executed. And also, I don't believe that `setAttribute('async', 'defer')` is valid, there need to be two entries `setAttribute('async', 'true')` and `setAttribute('defer', 'true')` (I think, not tested).

> [@Sean-McG](#):
>
> it needs the script to be added to the page as it listens for msgs.

Not sure what you mean by that but I think what you meant was that you want the script to `run` when a message is received? If so, you need to use an Angular v1 `watch` function.

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [27 April 2022 17:25 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/5 "2022-04-27T17:25:39Z")

</div>

> [@Sean-McG](#):
>
> As the number of tabs grows, this makes maintaining the code difficult, as any changes need to be duplicated many times in each template.

I thought you wanted to maintain the script in one place?  
The script is loaded and will then run on. The alert() in the simple example only runs once unless you refresh, that may of confused the issue.  
try this

```auto
[{"id":"93d1e86d.a97468","type":"http in","z":"bf9e1e33.030598","name":"","url":"/js_script","method":"get","upload":false,"swaggerDoc":"","x":150,"y":60,"wires":[["710d926e.2f1d6c"]]},{"id":"710d926e.2f1d6c","type":"template","z":"bf9e1e33.030598","name":"","field":"payload","fieldType":"msg","format":"handlebars","syntax":"mustache","template":"var value = \"hello world\"; \nthis.scope.action = function() { return value; }","output":"str","x":300,"y":20,"wires":[["5fb30c14.5253fc"]]},{"id":"5fb30c14.5253fc","type":"http response","z":"bf9e1e33.030598","name":"","statusCode":"","headers":{},"x":400,"y":60,"wires":[]},{"id":"c860115e.5cea28","type":"inject","z":"bf9e1e33.030598","name":"load script","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"tab\":\"\"}","payloadType":"json","x":510,"y":20,"wires":[["a43dc4b9.dd5e08"]]},{"id":"a43dc4b9.dd5e08","type":"ui_ui_control","z":"bf9e1e33.030598","name":"","events":"all","x":680,"y":40,"wires":[[]]},{"id":"528140c6.f07058","type":"inject","z":"bf9e1e33.030598","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":250,"y":140,"wires":[["a4c28729.b95928"]]},{"id":"a4c28729.b95928","type":"ui_template","z":"bf9e1e33.030598","group":"8b5cde76.edd58","name":"","order":8,"width":0,"height":0,"format":"<script type=\"text/javascript\" src=\"/js_script\"></script>\n<md-button ng-click=\"send({payload:action()})\">\n Click me to send a hello world\n</md-button>","storeOutMessages":true,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":450,"y":140,"wires":[["c114099e.6af7f"]]},{"id":"c114099e.6af7f","type":"debug","z":"bf9e1e33.030598","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":640,"y":180,"wires":[]},{"id":"8b5cde76.edd58","type":"ui_group","name":"default","tab":"8f03e639.85956","order":1,"disp":false,"width":"12","collapse":false},{"id":"8f03e639.85956","type":"ui_tab","name":"Home","icon":"dashboard","order":2,"disabled":false,"hidden":false}]

```

Edit the script in the template, refresh the page and the new script is loaded.  
[edit] Or use ui-control to refresh dashboard tabs when you have edited the script. I added it to above example.

---

<div class="post-metadata">

**Author:** ![Sean-McG](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sean-mcg/32/54677_2.png) [@Sean-McG](https://discourse.nodered.org/u/Sean-McG)\
**Post date:** [27 April 2022 18:01 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/6 "2022-04-27T18:01:13Z")

</div>

"sound of cogs turning"

I tried this to see if I could load MY script -

```auto
[{"id":"8cf6d0f2f015e72c","type":"ui_template","z":"ccaa93c6.20c32","group":"09bc015144beae74","name":"Weather","order":8,"width":0,"height":0,"format":"<script type=\"text/javascript\" src=\"/js_script\"></script>","storeOutMessages":false,"fwdInMessages":false,"resendOnRefresh":true,"templateScope":"local","className":"","x":700,"y":1480,"wires":[["32342ba7.177b04"]]},{"id":"7ca9c3d6e3b9dc26","type":"file in","z":"ccaa93c6.20c32","name":"","filename":"/home/pi/.node-red/public/myjs/header.js","format":"utf8","chunk":false,"sendError":false,"encoding":"none","allProps":false,"x":760,"y":1540,"wires":[["5fb30c14.5253fc"]]},{"id":"93d1e86d.a97468","type":"http in","z":"ccaa93c6.20c32","name":"","url":"/js_script","method":"get","upload":false,"swaggerDoc":"","x":490,"y":1540,"wires":[["7ca9c3d6e3b9dc26"]]},{"id":"5fb30c14.5253fc","type":"http response","z":"ccaa93c6.20c32","name":"","statusCode":"","headers":{},"x":1010,"y":1540,"wires":[]},{"id":"528140c6.f07058","type":"inject","z":"ccaa93c6.20c32","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":500,"y":1480,"wires":[["8cf6d0f2f015e72c"]]},{"id":"09bc015144beae74","type":"ui_group","name":"data","tab":"575545d5645126b6","order":1,"disp":true,"width":"24","collapse":false,"className":""},{"id":"575545d5645126b6","type":"ui_tab","name":"Weather","icon":"dashboard","disabled":false,"hidden":false}]

```

extract from MY script -

```auto
var theScope = scope;

        var myButton = document.getElementById("my-fault-button");
        if(!myButton) {
        var button = new Image();
        button.src = ''
        button.height = '50' ;
        button.addEventListener('click', fault);
        button.id = 'my-fault-button'
        button.style='margin: 20px auto'
        var titleBar = document.getElementById("nr-dashboard-toolbar");
        titleBar.append(button);
        }
        function fault(){
        msg={payload:"",topic:"fault"}
        theScope.send(msg);
        }

```

I "think" its working on one tab, need to do more tests. odd thing is I see lots of errors in firefox console, but not in chrome ?

```auto

Error: [$rootScope:inprog] http://errors.angularjs.org/1.8.2/$rootScope/inprog?p0=%24digest

```

---

<div class="post-metadata">

**Author:** ![Sean-McG](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/sean-mcg/32/54677_2.png) [@Sean-McG](https://discourse.nodered.org/u/Sean-McG)\
**Post date:** [27 April 2022 18:25 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/7 "2022-04-27T18:25:19Z")

</div>

@E1cid @TotallyInformation Thanks for the help, so it turns out to be much easier than I thought 😉

I'm loading the script from disk and "serving" it to each template node. This means I can just edit the script once without having to update 30 odd templates 😃 🍻

---

<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:** [11 May 2022 18:25 UTC](https://discourse.nodered.org/t/add-a-script-dynamically/61878/8 "2022-05-11T18:25:22Z")

</div>

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