# Convert template for Dashboard 1 to template for dashboard 2

**URL:** <https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411>\
**Category:** Dashboard\
**Tags:** dashboard-2, ui-template\
**Created:** [15 October 2024 13:41 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411 "2024-10-15T13:41:46Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Manuwa](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@Manuwa](https://discourse.nodered.org/u/Manuwa)\
**Post date:** [15 October 2024 13:41 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/1 "2024-10-15T13:41:46Z")

</div>

Hello dear forum.  
I am in the process of moving from Dashboard 1 to Dashboard 2. Most of it works.  
Unfortunately, I'm having a hard time getting my created templates to work on the new dashboard.  
Unfortunately I am not an expert in this area. I was happy that it ran under Dashboard 1.

Here is my template for the old dashboard.

```auto
[
    {
        "id": "5d2538ef5c48634d",
        "type": "ui_template",
        "z": "233f2e33b7762cdf",
        "g": "9adba24cdf37a851",
        "group": "3867402a42b1cb87",
        "name": "Pin_Unlock",
        "order": 1,
        "width": 0,
        "height": 0,
        "format": "<div ng-init=\"init()\" id=\"pin_insert\" class=\"dialog\">\n \n <div class=\"dialog_content\">\n \n <div class=\"dialog_header\">\n <span ng-click=\"closeDialog()\" class=\"close\">&times;</span>\n <h2 style=\"margin:10px\">Insert PIN</h2>\n </div>\n \n <div class=\"dialog_body\">\n\n <div layout=\"row\" layout-align=\"center\">\n <div class=\"number_placeholder\">\n {{passcode.substring(0, 1)}}\n </div>\n <div class=\"number_placeholder\">\n {{passcode.substring(1, 2)}}\n </div>\n <div class=\"number_placeholder\">\n {{passcode.substring(2, 3)}}\n </div>\n <div class=\"number_placeholder\">\n {{passcode.substring(3, 4)}}\n </div>\n </div>\n \n <div layout=\"column\" layout-align=\"center\" style=\"margin-top: 10px\">\n <div layout=\"row\" layout-align=\"center\">\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(1)\">1</md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(2)\">2</md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(3)\">3</md-button>\n </div>\n </div>\n <div layout=\"row\" layout-align=\"center\">\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(4)\">4</md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(5)\">5</md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(6)\">6</md-button>\n </div>\n </div>\n <div layout=\"row\" layout-align=\"center\">\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(7)\">7</md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(8)\">8</md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(9)\">9</md-button>\n </div>\n </div>\n <div layout=\"row\" layout-align=\"center\">\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"confirm()\">\n <ng-md-icon icon=\"done\" style=\"color:#fff;\"></ng-md-icon>\n </md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"add(0)\">0</md-button>\n </div>\n <div class=\"number_box\">\n <md-button class=\"pin\" ng-click=\"delete()\">\n <ng-md-icon icon=\"arrow_back\" style=\"color:#fff;\"></ng-md-icon>\n </md-button>\n </div>\n </div>\n </div> \n \n </div> <!--dialog_body-->\n </div> <!--dialog_content-->\n</div> <!--dialog-->\n\n\n<style>\n\n/* The Dialog (background) */\n.dialog {\n display: none; /* Hidden by default */\n position: fixed; /* Stay in place */\n z-index: 100; /* Sit on top */\n left: 0;\n top: 0;\n width: 100%; /* Full width */\n height: 100%; /* Full height */\n overflow: auto; /* Enable scroll if needed */\n background-color: rgb(0,0,0); /* Fallback color */\n background-color: rgba(0,0,0,0.4); /* Black w/ opacity */\n -webkit-transform: translateZ(0px);\n -webkit-transform: translate3d(0,0,0);\n -webkit-perspective: 1000;\n}\n\n.dialog_content {\n position: absolute;\n background-color: #E3E3E3;\n left: calc(50% - 200px);\n top: 90px;\n border-radius: 10px;\n padding: 0;\n width: 400px;\n box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);\n -webkit-animation-name: animatetop;\n animation-name: animatetop;\n animation-duration: 0.4s;\n}\n\n/* Media query for smartphones (to Fix?) */\n@media only screen and (min-device-width : 375px) and (max-device-width : 667px) { \n .dialog_content {\n margin-top: 5%;\n margin-left: 5%;\n}\n}\n\n/* Add Animation */\n@-webkit-keyframes animatetop {\n from {top: -300px; opacity: 0} \n to {top: 90; opacity: 1}\n}\n\n@keyframes animatetop {\n from {top: -300px; opacity: 0}\n to {top: 90; opacity: 1}\n}\n\n/* Dialog Header */\n.dialog_header {\n padding: 2px 16px;\n background-color: #2E2E2E;\n border-radius: 10px 10px 0 0;\n color: white;\n}\n\n/* Dialog Body */\n.dialog_body {\n padding: 5px;\n background-color: #000F1E;\n}\n\n/* The Close Button */\n.close {\n color: #E3E3E3;\n float: right;\n font-size: 42px;\n font-weight: bold;\n cursor: pointer;\n}\n\n.close:hover,\n.close:focus {\n color: #FF0000;\n text-decoration: none;\n cursor: pointer;\n}\n\n/* __ */\n.number_placeholder{\n width: 75px;\n height: 51px;\n margin: 20px;\n font-size: 30pt;\n text-align: center;\n border-bottom: 1px solid #00F243;\n color: #00F243;\n}\n\n/* Number container */\n.number_box{\n margin: 5px;\n}\n\n/* Buttons style */\n.pin {\n min-height: 75px;\n min-width: 75px;\n font-weight: bold;\n margin: 0px 10px 10px 0px;\n box-shadow: 4px 4px 6px 0 #1A1A1A;\n background-color: #2E2E2E;\n color: #fff;\n font-size: 15pt;\n}\n\n.pin:not([disabled]):hover {\n background-color:#00F243;\n}\n\n.btn1 {\n color : rgb(49, 46, 46);\n background-color: rgba(255, 222, 121, 0.96);\n border-radius: 10px 0 0 10px;\n font-size: 24px;\n}\n\n.btn1:not([disabled]):hover {\n background-color: rgba(107, 103, 91, 0.96);\n color: white;\n}\n\n.btn1[disabled] {\n color : rgb(187, 187, 187);\n background-color: rgba(230, 230, 229, 0.96);\n}\n\n</style>\n\n<script>\n\n/**\n * pin_dialog.js\n * Node-Red UI template for Node-Red Dashboard. \n * Custom dialog that asks for a PIN to allow actions\n * Enjoy it :). \n * -- Daniel\n *\n *\n * @license The Unlicense, http://unlicense.org/\n * @version 0.2\n * @author Daniel Lando, https://github.com/robertsLando\n * @updated 2019-03-18\n * @link ----\n *\n *\n */\n\nvar dialog;\n\n/* ==== */\n(function(scope) {\n \n scope.passcode = \"\";\n scope.payload = \"\";\n scope.inited = false;\n \n scope.init = function() {\n scope.passcode = \"\";\n //Hide the md-panel\n $('#pin_insert').parent().parent().css(\"display\", \"none\");\n //This trick make it works on smartphones too :)\n dialog = $('#pin_insert').detach();\n //remove any previously added pin dialog\n $('.dialog').remove();\n }\n \n scope.showDialog = function() {\n dialog.appendTo(document.body);\n dialog.css(\"display\", \"block\");\n }\n \n scope.closeDialog = function(){\n dialog.css(\"display\", \"none\");\n }\n \n scope.add = function(value) {\n if(scope.passcode.length < 4) {\n scope.passcode = scope.passcode + value;\n if(scope.passcode.length == 4) {\n console.log(\"The four digit code was entered\");\n \n }\n }\n }\n \n scope.delete = function() {\n if(scope.passcode.length > 0) {\n scope.passcode = scope.passcode.substring(0, scope.passcode.length - 1);\n }\n }\n \n scope.confirm = function() {\n if(scope.passcode.length == 4) {\n scope.send({passcode: scope.passcode, payload : scope.payload});\n scope.closeDialog();\n scope.passcode = \"\";\n scope.payload = \"\";\n }\n }\n\n scope.$watch('msg', function(data) {\n if(data && data.topic){\n switch(data.topic){\n case \"show\":\n if(scope.inited){\n scope.payload = data.payload;\n scope.showDialog();\n }\n else\n scope.inited = true;\n break;\n case \"close\": \n scope.closeDialog(); \n break;\n }\n }\n });\n})(scope);\n\n</script>\n",
        "storeOutMessages": false,
        "fwdInMessages": false,
        "resendOnRefresh": false,
        "templateScope": "local",
        "className": "",
        "x": 250,
        "y": 320,
        "wires": [
            [
                "1472f0d237a8a975",
                "629cda73f88188e3"
            ]
        ]
    },
    {
        "id": "3867402a42b1cb87",
        "type": "ui_group",
        "name": "pin",
        "tab": "d34b32fd3e0c8e11",
        "order": 6,
        "disp": false,
        "width": "1",
        "collapse": false,
        "className": "balken"
    },
    {
        "id": "d34b32fd3e0c8e11",
        "type": "ui_tab",
        "name": "Auswahl",
        "icon": "dashboard",
        "order": 2,
        "disabled": false,
        "hidden": true
    }
]

```

and here only the content of the template:

```auto
<div ng-init="init()" id="pin_insert" class="dialog">
    
    <div class="dialog_content">
        
        <div class="dialog_header">
            <span ng-click="closeDialog()" class="close">&times;</span>
            <h2 style="margin:10px">Insert PIN</h2>
        </div>
        
        <div class="dialog_body">

           <div layout="row" layout-align="center">
                <div class="number_placeholder">
                    {{passcode.substring(0, 1)}}
                </div>
                <div class="number_placeholder">
                    {{passcode.substring(1, 2)}}
                </div>
                <div class="number_placeholder">
                    {{passcode.substring(2, 3)}}
                </div>
                <div class="number_placeholder">
                    {{passcode.substring(3, 4)}}
                </div>
            </div>
            
            <div layout="column" layout-align="center" style="margin-top: 10px">
                <div layout="row" layout-align="center">
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(1)">1</md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(2)">2</md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(3)">3</md-button>
                    </div>
                </div>
                 <div layout="row" layout-align="center">
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(4)">4</md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(5)">5</md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(6)">6</md-button>
                    </div>
                </div>
                 <div layout="row" layout-align="center">
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(7)">7</md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(8)">8</md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(9)">9</md-button>
                    </div>
                </div>
                 <div layout="row" layout-align="center">
                    <div class="number_box">
                        <md-button class="pin" ng-click="confirm()">
                            <ng-md-icon icon="done" style="color:#fff;"></ng-md-icon>
                        </md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="add(0)">0</md-button>
                    </div>
                    <div class="number_box">
                        <md-button class="pin" ng-click="delete()">
                            <ng-md-icon icon="arrow_back" style="color:#fff;"></ng-md-icon>
                        </md-button>
                    </div>
                </div>
            </div> 
          
        </div> <!--dialog_body-->
    </div> <!--dialog_content-->
</div> <!--dialog-->

<style>

/* The Dialog (background) */
.dialog {
    display: none; /* Hidden by default */
    position: fixed; /* Stay in place */
    z-index: 100; /* Sit on top */
    left: 0;
    top: 0;
    width: 100%; /* Full width */
    height: 100%; /* Full height */
    overflow: auto; /* Enable scroll if needed */
    background-color: rgb(0,0,0); /* Fallback color */
    background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
    -webkit-transform: translateZ(0px);
    -webkit-transform: translate3d(0,0,0);
    -webkit-perspective: 1000;
}

.dialog_content {
    position: absolute;
    background-color: #E3E3E3;
    left: calc(50% - 200px);
    top: 90px;
    border-radius: 10px;
    padding: 0;
    width: 400px;
    box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
    -webkit-animation-name: animatetop;
    animation-name: animatetop;
    animation-duration: 0.4s;
}

/* Media query for smartphones (to Fix?) */
@media only screen and (min-device-width : 375px) and (max-device-width : 667px) { 
    .dialog_content {
    margin-top: 5%;
    margin-left: 5%;
}
}

/* Add Animation */
@-webkit-keyframes animatetop {
    from {top: -300px; opacity: 0} 
    to {top: 90; opacity: 1}
}

@keyframes animatetop {
    from {top: -300px; opacity: 0}
    to {top: 90; opacity: 1}
}

/* Dialog Header */
.dialog_header {
    padding: 2px 16px;
    background-color: #2E2E2E;
    border-radius: 10px 10px 0 0;
    color: white;
}

/* Dialog Body */
.dialog_body {
    padding: 5px;
    background-color: #000F1E;
}

/* The Close Button */
.close {
    color: #E3E3E3;
    float: right;
    font-size: 42px;
    font-weight: bold;
    cursor: pointer;
}

.close:hover,
.close:focus {
    color: #FF0000;
    text-decoration: none;
    cursor: pointer;
}

/* __ */
.number_placeholder{
    width: 75px;
    height: 51px;
    margin: 20px;
    font-size: 30pt;
    text-align: center;
    border-bottom: 1px solid #00F243;
    color: #00F243;
}

/* Number container */
.number_box{
    margin: 5px;
}

/* Buttons style */
.pin {
    min-height: 75px;
    min-width: 75px;
    font-weight: bold;
    margin: 0px 10px 10px 0px;
    box-shadow: 4px 4px 6px 0 #1A1A1A;
    background-color: #2E2E2E;
    color: #fff;
    font-size: 15pt;
}

.pin:not([disabled]):hover {
    background-color:#00F243;
}

.btn1 {
  color : rgb(49, 46, 46);
  background-color: rgba(255, 222, 121, 0.96);
  border-radius: 10px 0 0 10px;
  font-size: 24px;
}

.btn1:not([disabled]):hover {
  background-color: rgba(107, 103, 91, 0.96);
  color: white;
}

.btn1[disabled] {
  color : rgb(187, 187, 187);
  background-color: rgba(230, 230, 229, 0.96);
}

</style>

<script>

/**
 * pin_dialog.js
 * Node-Red UI template for Node-Red Dashboard. 
 * Custom dialog that asks for a PIN to allow actions
 * Enjoy it :). 
 * -- Daniel
 *
 *
 * @license The Unlicense, http://unlicense.org/
 * @version 0.2
 * @author Daniel Lando, https://github.com/robertsLando
 * @updated 2019-03-18
 * @link ----
 *
 *
 */

var dialog;

/* ==== */
(function(scope) {
    
    scope.passcode = "";
    scope.payload = "";
    scope.inited = false;
    
    scope.init = function() {
        scope.passcode = "";
        //Hide the md-panel
        $('#pin_insert').parent().parent().css("display", "none");
        //This trick make it works on smartphones too :)
        dialog = $('#pin_insert').detach();
        //remove any previously added pin dialog
        $('.dialog').remove();
    }
    
    scope.showDialog = function() {
        dialog.appendTo(document.body);
        dialog.css("display", "block");
    }
    
    scope.closeDialog = function(){
        dialog.css("display", "none");
    }
    
    scope.add = function(value) {
        if(scope.passcode.length < 4) {
            scope.passcode = scope.passcode + value;
            if(scope.passcode.length == 4) {
                console.log("The four digit code was entered");
                   
            }
        }
    }
 
    scope.delete = function() {
        if(scope.passcode.length > 0) {
            scope.passcode = scope.passcode.substring(0, scope.passcode.length - 1);
        }
    }
    
    scope.confirm = function() {
        if(scope.passcode.length == 4) {
            scope.send({passcode: scope.passcode, payload : scope.payload});
            scope.closeDialog();
            scope.passcode = "";
            scope.payload = "";
        }
    }

    scope.$watch('msg', function(data) {
        if(data && data.topic){
            switch(data.topic){
               case "show":
                   if(scope.inited){
                        scope.payload = data.payload;
                        scope.showDialog();
                   }
                   else
                        scope.inited = true;
                break;
                case "close": 
                    scope.closeDialog(); 
                break;
            }
        }
    });
})(scope);

</script>

```

Can someone perhaps give me some food for thought, or assess whether it works at all with the new dashboard. Or whether there are simpler methods.

The template opens a dialog in which you have to enter a pin and then confirm it.

Many thanks for any help  
Manuel

---

<div class="post-metadata">

**Author:** ![Steve-Mcl](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/steve-mcl/32/4826_2.png) [@Steve-Mcl](https://discourse.nodered.org/u/Steve-Mcl)\
**Post date:** [15 October 2024 13:50 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/2 "2024-10-15T13:50:15Z")

</div>

Old dashboard uses the long depreciated angular v1

New dashboard uses [vue](https://vuejs.org/) + [vuetify](https://vuetifyjs.com/en/components/all/#containment)

The new dashboard has extensive docs including a migration guide: [Dashboard 1.0 Migration Guide | Node-RED Dashboard 2.0](https://dashboard.flowfuse.com/user/migration.html)

On top of what I wrote here: [Subflow - UI Group - #11 by Steve-Mcl](https://discourse.nodered.org/t/subflow-ui-group/92068/11) , most things have an immediate alternative. e.g. `md-button` becomes `v-btn` and the docs for `v-btn` are here: [Button component — Vuetify](https://vuetifyjs.com/en/components/buttons/#usage)

---

<div class="post-metadata">

**Author:** ![Manuwa](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@Manuwa](https://discourse.nodered.org/u/Manuwa)\
**Post date:** [15 October 2024 14:19 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/3 "2024-10-15T14:19:46Z")

</div>

Thank you very much,

will have a look there

---

<div class="post-metadata">

**Author:** ![hotNipi](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/hotnipi/32/383_2.png) [@hotNipi](https://discourse.nodered.org/u/hotNipi)\
**Post date:** [15 October 2024 16:24 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/4 "2024-10-15T16:24:56Z")

</div>

Search from web `pin pad Vue vuetify`. Some examples you can find. Sure they are not source for copy-paste-happy route but many things are usable for sure.

---

<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:** [15 October 2024 16:43 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/5 "2024-10-15T16:43:54Z")

</div>

> [@Manuwa](#):
>
> The template opens a dialog in which you have to enter a pin and then confirm it.

Worth noting, that with new Dashboard, you have [Dialog's built in too](https://dashboard.flowfuse.com/nodes/config/ui-group.html#dialog-groups), so your template would just need to have the PIN logic inside, then that could live in a "Dialog"-typed group

---

<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:** [15 October 2024 16:50 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/6 "2024-10-15T16:50:59Z")

</div>

We also support all Vuetify components by default inside the template node, and they do have a [OTP component](https://vuetifyjs.com/en/components/otp-input/#usage) which may be useful for you.

You can read more about our Template node [here](https://dashboard.flowfuse.com/nodes/widgets/ui-template.html).

I will also be recording a tutorial about the template node this week, targeted at new users, so might be worth waiting for that too. I will publish it to the [FlowFuse YouTube Channel](https://www.youtube.com/@FlowFuseInc)

---

<div class="post-metadata">

**Author:** ![Manuwa](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@Manuwa](https://discourse.nodered.org/u/Manuwa)\
**Post date:** [15 October 2024 18:11 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/7 "2024-10-15T18:11:16Z")

</div>

Many thanks for the tip. I'll see how far I can get.

---

<div class="post-metadata">

**Author:** ![Manuwa](https://avatars.discourse-cdn.com/v4/letter/m/858c86/32.png) [@Manuwa](https://discourse.nodered.org/u/Manuwa)\
**Post date:** [15 October 2024 18:12 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/8 "2024-10-15T18:12:34Z")

</div>

Many thanks to you too. Then I will wait. That will certainly help me.

---

<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:** [14 November 2024 18:12 UTC](https://discourse.nodered.org/t/convert-template-for-dashboard-1-to-template-for-dashboard-2/92411/9 "2024-11-14T18:12:49Z")

</div>

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