# Going from ui-template 1.0 vs 2.0 fails

**URL:** <https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374>\
**Category:** Dashboard\
**Tags:** dashboard-2\
**Created:** [5 January 2025 18:56 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374 "2025-01-05T18:56:00Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![grawsom](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/grawsom/32/53070_2.png) [@grawsom](https://discourse.nodered.org/u/grawsom)\
**Post date:** [5 January 2025 18:56 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/1 "2025-01-05T18:56:00Z")

</div>

I have used this flow ex. [flow](https://flows.nodered.org/flow/58e1c6f50c965283f0cf0da1fb5bbc5e) (ui-template) in Dashboard 1.0, but can't get it to work in 2.0

- It loads the map, butif you refresh the page it goes black.
- Also need to remove the "scope", but then I can't find out to format the code in template so I can use "this.send"

Any help that I can get.

I have seen the YT videos over and over to see if I have missed out something.  
Need more explaning of all the new stuff in ui-template 2.0

```auto
[{"id":"fd704f60baed6544","type":"ui_template","z":"0aaef064838ae5d3","group":"7e85723e91f540b8","name":"Leaflet","order":3,"width":12,"height":7,"format":"<link rel=\"stylesheet\" href=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.css\"\n integrity=\"sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=\" crossorigin=\"\" />\n<!-- Make sure you put this AFTER Leaflet's CSS -->\n<script src=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.js\"\n integrity=\"sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=\" crossorigin=\"\"></script>\n <style>\n #map {\n /*from www.java2s.com*/\n height: 500px;\n }\n \n .leaflet-grab {\n cursor: auto;\n }\n \n .leaflet-dragging .leaflet-grab {\n cursor: move;\n }\n </style>\n\n<script>\n (function() {\n const cScope = this.scope;\n setTimeout(function () {\n \n \tvar map = L.map('map').setView([48, 11], 10);\n let marker;\n \n \tL.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {\n \t\tmaxZoom: 20,\n attribution: '© OpenStreetMap'\n \t}).addTo(map);\n \t\n \tmap.on('click', function(e) {\n cScope.send(e.latlng);\n if (marker) {\n map.removeLayer(marker);\n };\n marker = L.marker(e.latlng).addTo(map);\n });\n \n setTimeout(function () {\n map.invalidateSize();\n }, 100);\n }, 300);\n })();\n</script>\n<div id=\"map\"></div>\n<!-- <div id=\"map\" style=\"width: 100%; height: 400px;\"></div> -->","storeOutMessages":true,"fwdInMessages":true,"resendOnRefresh":false,"templateScope":"local","className":"","x":650,"y":440,"wires":[["6dcbe4e3a0dd9739"]]},{"id":"7e85723e91f540b8","type":"ui_group","name":"iFrame","tab":"7ca1e2ce075bc580","order":3,"disp":true,"width":12,"collapse":false,"className":""},{"id":"7ca1e2ce075bc580","type":"ui_tab","name":"Home","icon":"dashboard","order":3,"disabled":false,"hidden":false}]

```

/ Ivan

---

<div class="post-metadata">

**Author:** ![joepavitt](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/joepavitt/32/59722_2.png) [@joepavitt](https://discourse.nodered.org/u/joepavitt)\
**Post date:** [6 January 2025 13:52 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/2 "2025-01-06T13:52:48Z")

</div>

Can you share your progress with the Dashboard 2.0 equivalent so I can take a look please? The flow you've included is the Dashboard 1.0 node

---

<div class="post-metadata">

**Author:** ![grawsom](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/grawsom/32/53070_2.png) [@grawsom](https://discourse.nodered.org/u/grawsom)\
**Post date:** [6 January 2025 14:45 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/3 "2025-01-06T14:45:48Z")

</div>

I have tried this, have an console.log, that works.  
But if I refresh goes blank.  
Also when using this it goes from pointer to hand when hover over map.

Here is my 2.0 so far

```auto
[{"id":"2fad9a3f33204169","type":"ui-template","z":"e005ff7061ee2417","group":"c72c76e21d82b7d1","page":"","ui":"","name":"Geo","order":1,"width":0,"height":0,"head":"","format":"<template>\n <link rel=\"stylesheet\" href=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.css\"\n integrity=\"sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=\" crossorigin=\"\" />\n\n <div id=\"map\"></div>\n <!-- <div id=\"map\" style=\"width: 100%; height: 400px;\"></div> -->\n</template>\n\n<!-- Make sure you put this AFTER Leaflet's CSS -->\n<script src=\"https://unpkg.com/leaflet@1.9.4/dist/leaflet.js\"\n integrity=\"sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=\" crossorigin=\"\"></script>\n \n\n<script>\n var map = L.map('map').setView([48, 11], 10);\n let marker;\n\n map.on('click', function(e) {\n //cScope.send(e.latlng);\n //this.send(e.latlng);\n console.log(e.latlng);\n if (marker) {\n map.removeLayer(marker);\n };\n marker = L.marker(e.latlng).addTo(map);\n });\n\n L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {\n maxZoom: 20,\n attribution: '© OpenStreetMap'\n }).addTo(map);\n\n \n</script>\n<style>\n #map {\n /*from www.java2s.com*/\n height: 500px;\n }\n \n .leaflet-grab {\n cursor: auto;\n }\n \n .leaflet-dragging .leaflet-grab {\n cursor: move;\n }\n </style>","storeOutMessages":true,"passthru":true,"resendOnRefresh":true,"templateScope":"local","className":"","x":110,"y":620,"wires":[["72d4d1e46ee3745d"]]},{"id":"c72c76e21d82b7d1","type":"ui-group","name":"My Group","page":"9d4bc1caffe751ab","width":"12","height":"10","order":1,"showTitle":true,"className":"","visible":"true","disabled":"false","groupType":"default"},{"id":"9d4bc1caffe751ab","type":"ui-page","name":"My Geo","ui":"a171c8195c1b8e57","path":"/ui-button-example","icon":"button-pointer","layout":"grid","theme":"9d8bfd7e0d216779","breakpoints":[{"name":"Default","px":"0","cols":"3"},{"name":"Tablet","px":"576","cols":"6"},{"name":"Small Desktop","px":"768","cols":"9"},{"name":"Desktop","px":"1024","cols":"12"}],"order":1,"className":"","visible":"true","disabled":"false"},{"id":"a171c8195c1b8e57","type":"ui-base","name":"My Dashboard","path":"/dashboard","appIcon":"","includeClientData":true,"acceptsClientConfig":["ui-control","ui-gauge","ui-chart","ui-form","ui-text-input","ui-file-input","ui-button","ui-button-group","ui-dropdown","ui-radio-group","ui-slider","ui-switch","ui-text","ui-table","ui-markdown","ui-notification","ui-template"],"showPathInSidebar":false,"showPageTitle":true,"navigationStyle":"icon","titleBarStyle":"default","showReconnectNotification":false,"notificationDisplayTime":5,"showDisconnectNotification":false},{"id":"9d8bfd7e0d216779","type":"ui-theme","name":"Default Theme","colors":{"surface":"#ffffff","primary":"#15617e","bgPage":"#eeeeee","groupBg":"#ffffff","groupOutline":"#cccccc"},"sizes":{"pagePadding":"12px","groupGap":"12px","groupBorderRadius":"4px","widgetGap":"12px"}}]

```

---

<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:** [6 January 2025 16:02 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/4 "2025-01-06T16:02:59Z")

</div>

I believe the problem is that you are trying to execute code before the leaflet.js script has loaded.  
There is an example in the Dashboard ui\_template docs about [Loading External Dependencies](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html#loading-external-dependencies) that uses a timer to wait for the script to load.

Adapted code :

```html
<template>
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
        integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />

    <div id="map"></div>
    <!-- <div id="map" style="width: 100%; height: 400px;"></div> -->
</template>

<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"
    integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
   

<script>
    function init () {
        var map = L.map('map').setView([48, 11], 10);
        let marker;
    
        map.on('click', function(e) {
            //cScope.send(e.latlng);
            //this.send(e.latlng);
            console.log(e.latlng);
            if (marker) {
            map.removeLayer(marker);
            };
            marker = L.marker(e.latlng).addTo(map);
        });
        
        L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
            maxZoom: 20,
            attribution: '© OpenStreetMap'
        }).addTo(map);
    }

    // run this code when the widget is built
    let interval = setInterval(() => {
        if (window.L) {
            // call an init() to use leaflet
            init();
            // leaflet.js is loaded, so we can now use it
            clearInterval(interval);
        }
    }, 100);

</script>
<style>
    #map {
    /*from www.java2s.com*/
    height: 500px;
    }
    
    .leaflet-grab {
    cursor: auto;
    }
    
    .leaflet-dragging .leaflet-grab {
    cursor: move;
    }
</style>

```

---

<div class="post-metadata">

**Author:** ![grawsom](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/grawsom/32/53070_2.png) [@grawsom](https://discourse.nodered.org/u/grawsom)\
**Post date:** [6 January 2025 19:40 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/5 "2025-01-06T19:40:11Z")

</div>

@UnborN  
Great showing how that was solved, now I just need to get the feedback to show up in NR.  
map.on('click........  
I have console.log and it returns fine, but this.send(e.latlng); gives an error in console "Uncaught TypeError: this.send is not a function" and stops.

I'm sure it needs to be configured in another way.  
Really need to learn some more stuff.

---

<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:** [6 January 2025 21:31 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/6 "2025-01-06T21:31:28Z")

</div>

I dont know how to explain it very well but .. when you call `this` inside a function .. as we did ...  
`this` is not anymore the original `this` .. you can read more about it here ([link](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this))

So to solve it you can assign `this` (that has the send function attached to it) to another variable  
`let cScope = this;` at the beginning of you script or maybe use arrow functions everywhere.

Example of 1st method

```auto
<script>

    let cScope = this;

    function init () {
        var map = L.map('map').setView([48, 11], 10);
        let marker;
    
        map.on('click', function(e) {
            //cScope.send(e.latlng);
            cScope.send({payload : e.latlng});
            console.log(e.latlng);
            if (marker) {
            map.removeLayer(marker);
            };
            marker = L.marker(e.latlng).addTo(map);
        });
        
        L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
            maxZoom: 20,
            attribution: '© OpenStreetMap'
        }).addTo(map);
    }

    // run this code when the widget is built
    let interval = setInterval(() => {
        if (window.L) {
            // call an init() to use leaflet
            init();
            // leaflet.js is loaded, so we can now use it
            clearInterval(interval);
        }
    }, 100);

</script>

```

---

<div class="post-metadata">

**Author:** ![grawsom](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/grawsom/32/53070_2.png) [@grawsom](https://discourse.nodered.org/u/grawsom)\
**Post date:** [6 January 2025 21:41 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/7 "2025-01-06T21:41:31Z")

</div>

This is just what I needed, you saved my day..  
And learned something new

---

<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:** [7 January 2025 17:20 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/8 "2025-01-07T17:20:47Z")

</div>

> [@UnborN](#):
>
> maybe use arrow functions everywhere.

Arrow functions are generally better.

---

<div class="post-metadata">

**Author:** ![grawsom](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/grawsom/32/53070_2.png) [@grawsom](https://discourse.nodered.org/u/grawsom)\
**Post date:** [7 January 2025 18:22 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/9 "2025-01-07T18:22:08Z")

</div>

> [@TotallyInformation](#):
>
> Arrow functions are generally better.

This is something I don't know what means 🤔, maybe when I see it.  
Could you explain?

---

<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:** [7 January 2025 18:36 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/10 "2025-01-07T18:36:37Z")

</div>

> [@grawsom](#):
>
> maybe when I see it.

here is the code example using Arrow Functions

```auto
<script>

    let init = () => {
        var map = L.map('map').setView([48, 11], 10);
        let marker;
    
        map.on('click', (e) => {
            this.send({payload : e.latlng});
            if (marker) {
            map.removeLayer(marker);
            };
            marker = L.marker(e.latlng).addTo(map);
        });
        
        L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
            maxZoom: 20,
            attribution: '© OpenStreetMap'
        }).addTo(map);
    }

    // run this code when the widget is built
    let interval = setInterval(() => {
        if (window.L) {
            // call an init() to use leaflet
            init();
            // leaflet.js is loaded, so we can now use it
            clearInterval(interval);
        }
    }, 100);

</script>

```

Both `init` and the `map.on` callback are defined with arrow function syntax.  
This way you can use `this.send` inside of it because `this` is _unaffected_ since arrow functions dont create a new `this` binding.

---

<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:** [7 January 2025 20:03 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/11 "2025-01-07T20:03:53Z")

</div>

Here you go.

> **[Arrow function expressions - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)**
>
> An arrow function expression is a compact alternative to a traditional function expression, with some semantic differences and deliberate limitations in usage:

Though UnborN has already provided a brief explanation.

It took me a while to get my head around them to be honest.

The most important aspect is that arrow fns do not create a new `this` context. They inherit the outer context.

The other thing to remember is that they are "anonymous" functions by default - they don't have a name. This actually makes them good for callbacks like you are seeing in the above examples. If you need to give them a name, you can do like this:

```auto
const bob2 = (bob) => bob * 2;

```

You can also see from the above that they can be a lot more terse than standard functions, this example does not have an explicit `return` statement for example but it absolutely does return a value. That only works for single statement functions though.

---

<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:** [21 January 2025 20:04 UTC](https://discourse.nodered.org/t/going-from-ui-template-1-0-vs-2-0-fails/94374/12 "2025-01-21T20:04:46Z")

</div>

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