# Ui-template set httpstatic for dashboard 2

**URL:** <https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591>\
**Category:** General\
**Tags:** dashboard-2\
**Created:** [29 April 2024 17:21 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591 "2024-04-29T17:21:08Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![denissanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/denissanga/32/48346_2.png) [@denissanga](https://discourse.nodered.org/u/denissanga)\
**Post date:** [29 April 2024 17:21 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/1 "2024-04-29T17:21:08Z")

</div>

Hi all, I'm trying using dashboard2 and I would understand where locate the external javascript scripts

for dashboard 1 I set httpstatic path in the setting file adding the folder where my script are located in "/static/" and I call them from ui with the following line

```auto
{path: '/home/pi/.node-red/html/', root: "/static/"},

```

**the same not works in the dashboard2 where the page is "[https://myip:1880/dashboard/page](https://myip:1880/dashboard/page)"**

can someone help me?  
many thanks

---

<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 April 2024 22:24 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/2 "2024-04-29T22:24:45Z")

</div>

lets say you have an `image.jpg` in your static folder  
you place the image in `/home/pi/.node-red/html/` and  
it should be served at `https://localhost:1880/static/image.jpg`  
If you visit the link directly can you see the asset / script ?

when it comes to loading the asset from dashboard .. since the dashboard is served from `/dashboard`  
im guessing you should go one level back `../` in order to access `/static` ?

example : `<script src="../static/myScript.js"></script> `

---

<div class="post-metadata">

**Author:** ![denissanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/denissanga/32/48346_2.png) [@denissanga](https://discourse.nodered.org/u/denissanga)\
**Post date:** [30 April 2024 06:22 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/3 "2024-04-30T06:22:55Z")

</div>

many thanks for your help

if i do

```auto
<img src="../static/img.jpeg" alt="test">

```

it works correctly but if I do

```auto
<script type="text/javascript" src="../static/js/jsqrscanner.nocache.js"></script>

```

it not works  
while in dashboard ver 1 if I do

```auto
<script type="text/javascript" src="/static/js/jsqrscanner.nocache.js"></script>

```

it works

---

<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 April 2024 07:46 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/4 "2024-04-30T07:46:11Z")

</div>

1. Do you have any errors in the browser console logs ?
2. It could be the case that the script doesnt load in time before the Dashboard 2 ui-template component runs its code. If thats the case see this post how a timer can be used to wait for the script to load ([link](https://discourse.nodered.org/t/how-to-configure-echarts-in-dashboard-2/87259/4))

---

<div class="post-metadata">

**Author:** ![denissanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/denissanga/32/48346_2.png) [@denissanga](https://discourse.nodered.org/u/denissanga)\
**Post date:** [30 April 2024 09:28 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/5 "2024-04-30T09:28:58Z")

</div>

many thanks for your help  
no error appears in web page console

if I try adding

```auto
export default {
       mounted() {
            let interval = setInterval(() => {
                if (window.jsqrscanner) {
                    clearInterval(interval);
                    // now it is loaded, we can initialise and use it
                }
            }, 100);
        }
   }

```

in the web console appears

```auto
index-CkQi99U4.js:236 errorCaptured SyntaxError: Unexpected token 'export'
    at Proxy.created (index-CkQi99U4.js:236:6486)
    at callWithErrorHandling (index-CkQi99U4.js:22:2165)
    at callWithAsyncErrorHandling (index-CkQi99U4.js:22:2273)
    at callWithAsyncErrorHandling (index-CkQi99U4.js:22:2412)
    at callHook$1 (index-CkQi99U4.js:22:35193)
    at applyOptions (index-CkQi99U4.js:22:34256)
    at finishComponentSetup (index-CkQi99U4.js:22:72406)
    at setupStatefulComponent (index-CkQi99U4.js:22:71538)
    at setupComponent (index-CkQi99U4.js:22:70927)
    at H (index-CkQi99U4.js:22:53467) Proxy(Object) {_: {…}, $socket: Socket, send: ƒ, submit: ƒ, …} https://vuejs.org/error-reference/#runtime-c

```

---

<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 April 2024 10:09 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/6 "2024-04-30T10:09:18Z")

</div>

is your javascript enclosed between `<script>` tags ?

Dashboard 2 has some changes from 1 .. it now uses Vue Components so you need to adapt your old code.  
You can read more about them [here](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#building-full-vue-components)

---

<div class="post-metadata">

**Author:** ![denissanga](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/denissanga/32/48346_2.png) [@denissanga](https://discourse.nodered.org/u/denissanga)\
**Post date:** [30 April 2024 10:13 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/7 "2024-04-30T10:13:36Z")

</div>

yes I put the code in script tag as follow

```auto

<script src="../static/js/jsqrscanner.nocache.js"></script>
<script type="text/javascript">
    export default {
        mounted() {
            let interval = setInterval(() => {
                if (window.jsqrscanner) {
                    clearInterval(interval);
                    console.log("init")
                }
            }, 100);
        }
    }
    function onQRCodeScanned(scannedText)
    {   
        var scannedTextMemo = document.getElementById("scannedTextMemo");
        if(scannedTextMemo)
        {    
            scannedTextMemo.value = scannedText;
            console.log({payload: scannedText});
        }
    }

    function provideVideo()
    {
        var n = navigator;
        if (n.mediaDevices && n.mediaDevices.getUserMedia)
        {
        return n.mediaDevices.getUserMedia({
            video: {
            facingMode: "environment"
            },
            audio: false
        });
        }    
        return Promise.reject('Your browser does not support getUserMedia');
    }

    function provideVideoQQ()
    {
        return navigator.mediaDevices.enumerateDevices()
        .then(function(devices) {
            console.log(devices);
            var exCameras = [];
            devices.forEach(function(device) {
                if (device.kind === 'videoinput') {
                    console.log(device.deviceId)
                    exCameras.push(device.deviceId)
            }
        });  
            return Promise.resolve(exCameras);
        }).then(function(ids){
            if(ids.length === 0)
            {
                console.log("error find camera")
                return Promise.reject('Could not find a webcam');
            }
            
            return navigator.mediaDevices.getUserMedia({
                video: {
                'optional': [{
                    'sourceId': ids.length === 1 ? ids[0] : ids[1]//this way QQ browser opens the rear camera
                    }]
                }
            });        
        });                
    }

    function JsQRScannerReady()
    { 
        var jbScanner = new JsQRScanner(onQRCodeScanned);
        jbScanner.setSnapImageMaxSize(300);
        var scannerParentElement = document.getElementById("scanner");
        if(scannerParentElement)
        {
            jbScanner.appendTo(scannerParentElement);
        }        
    }

</script>

```

---

<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 April 2024 12:20 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/8 "2024-04-30T12:20:35Z")

</div>

Try this code .. its partly based on the section of the D2 docs for [Loading External Dependencies](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#loading-external-dependencies)

```auto
<template>
  <div>
    <div class="qrscanner" id="scanner">
      <div><video class="qrPreviewVideo" autoplay="" src=""></video></div>
    </div>
    <textarea id="scannedTextMemo" class="textInput form-memo form-field-input textInput-readonly" rows="3" readonly=""></textarea>
  </div>
</template>
<script src="../static/js/jsqrscanner.nocache.js"></script>
<script>
  let interval = setInterval(() => {
    if (window.JsQRScanner) {
      clearInterval(interval);
      console.log("init");
      init();
    }
  }, 100);

  // init - jsqrscanner loaded
  function init() {

    function onQRCodeScanned(scannedText) {
      var scannedTextMemo = document.getElementById("scannedTextMemo");
      if (scannedTextMemo) {
        scannedTextMemo.value = scannedText;
        console.log({ payload: scannedText });
      }
    }

    function provideVideo() {
      var n = navigator;
      if (n.mediaDevices && n.mediaDevices.getUserMedia) {
        return n.mediaDevices.getUserMedia({
          video: {
            facingMode: "environment",
          },
          audio: false,
        });
      }
      return Promise.reject("Your browser does not support getUserMedia");
    }

    function provideVideoQQ() {
      return navigator.mediaDevices
        .enumerateDevices()
        .then(function (devices) {
          console.log(devices);
          var exCameras = [];
          devices.forEach(function (device) {
            if (device.kind === "videoinput") {
              console.log(device.deviceId);
              exCameras.push(device.deviceId);
            }
          });
          return Promise.resolve(exCameras);
        })
        .then(function (ids) {
          if (ids.length === 0) {
            console.log("error find camera");
            return Promise.reject("Could not find a webcam");
          }

          return navigator.mediaDevices.getUserMedia({
            video: {
              optional: [
                {
                  sourceId: ids.length === 1 ? ids[0] : ids[1], //this way QQ browser opens the rear camera
                },
              ],
            },
          });
        });
    }

    function JsQRScannerReady() {
      var jbScanner = new JsQRScanner(onQRCodeScanned);
      jbScanner.setSnapImageMaxSize(300);
      var scannerParentElement = document.getElementById("scanner");
      if (scannerParentElement) {
        jbScanner.appendTo(scannerParentElement);
      }
    }
  }
</script>

```

---

<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:** [29 July 2024 12:20 UTC](https://discourse.nodered.org/t/ui-template-set-httpstatic-for-dashboard-2/87591/9 "2024-07-29T12:20:59Z")

</div>

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