Uibuilder node shows a table

Hi, I used an uibuilder node to show a table on a screen. I am new in html and I like to add some global.vars to the same screen. But that is to difficult for me to combine JavaScript and html.

I like to add something like <div class="timerText">{{msg.timerText}}</div> to the html file to show that variable on screen. But I don't know how to do that. Is there some help?

My css file looks like:

/* Load defaults from `<userDir>/node_modules/node-red-contrib-uibuilder/front-end/uib-brand.min.css`
 * This version auto-adjusts for light/dark browser settings but might not be as complete.
 */
@import url("../uibuilder/uib-brand.min.css");

.timerText {
    font-size: 100px;

}

/* OR, load the defaults from the older `<userDir>/node_modules/node-red-contrib-uibuilder/front-end/uib-styles.css` */
/* @import url("../uibuilder/uib-styles.css"); */

My html file looks like:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>Scorebord</title>
    <meta name="description" content="Node-RED UI Builder - VueJS + bootstrap-vue default template" />

    <!-- <link rel="icon" href="./images/node-blue.ico" /> -->

    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />
    <!-- Your own CSS -->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all" />
  </head>
  <body>
    <h1>Scorebord</h1>
    
    <div id="app" v-cloak>
      <b-container id="app_container" class="mt-5">
        
        <div class="mt-5">
          <b-table striped hover small :items="items" ></b-table>
        </div>
      </b-container>
    </div>

    <!-- These MUST be in the right order. Note no leading / -->

    <!-- REQUIRED: Socket.IO is loaded only once for all instances. Without this, you don't get a websocket connection -->
    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>

    <!-- Vendor Libraries - Load in the right order, use minified, production versions for speed -->
    <script src="../uibuilder/vendor/vue/dist/vue.js"></script>
    <!-- dev version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.min.js"></script>   prod version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.runtime.min.js"></script>   prod version without component compiler -->
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
    <!-- Dev version -->
    <!-- <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.min.js"></script>   Prod version -->

    <!-- REQUIRED: Sets up Socket listeners and the msg object -->
    <script src="./uibuilderfe.js"></script>
    <!-- dev version -->
    <!-- <script src="./uibuilderfe.min.js"></script>     prod version -->

    <!-- OPTIONAL: You probably want this. Put your custom code here -->
    <script src="./index.js"></script>
  </body>
</html>

my js file looks like:

/* jshint browser: true, esversion: 5, asi: true */
/*globals Vue, uibuilder */
// @ts-nocheck
/*
  Copyright (c) 2021 Julian Knight (Totally Information)

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

  http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/
"use strict";

/** @see https://totallyinformation.github.io/node-red-contrib-uibuilder/#/front-end-library */

// eslint-disable-next-line no-unused-vars
const app = new Vue({
    el: "#app",

    data() {
        return {
            items: []  // table data 

        };
    }, // --- End of data --- //

    computed: {}, // --- End of computed --- //

    methods: {}, // --- End of methods --- //

    // Available hooks: beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed, activated,deactivated, errorCaptured

    /** Called after the Vue app has been created. A good place to put startup code */
    created: function () {
        // Example of retrieving data from uibuilder
        this.feVersion = uibuilder.get("version");

        uibuilder.start();
    }, // --- End of created hook --- //

    /** Called once all Vue component instances have been loaded and the virtual DOM built */
    mounted: function () {
        //console.debug('[indexjs:Vue.mounted] app mounted - setting up uibuilder watchers')
        // Start up uibuilder
        
        var app = this; // Reference to `this` in case we need it for more complex functions

        // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO
        uibuilder.onChange("msg", function (msg) {
            console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)
            app.items = msg.payload;  // save new table data from node-red in vue data items
            
        });


    }, // --- End of mounted hook --- //
}); // --- End of app1 --- //

// EOF

Hi, thanks for trying out UIBUILDER.

The format you've used there with the double-braces is something that a front-end FRAMEWORK is required for. UIBUILDER deliberately avoids forcing the use of a specific framework so that won't work.

However, UIBUILDER does provide some built-in Web Components. These are custom HTML tags you can use anywhere.

In this case, to replicate what you've got here, you would use something like:

<div class="timerText"><uib-var variable="uibuilder.msg.timerText"</uib-var></div>

You could drop the extra div and simply combine the class with the uib-var tag (though you may need to make uib-var display as a block to match div with display:block; in your css.

However, there is an even better and easier way for you. Since you want to display the data from a message from Node-RED, try this:

<div class="timerText" uib-topic="timer"></div>

Where "timer" is simply the msg.topic on your sent message. Also, instead of using msg.timerText, use msg.payload for that content. Then whenever you send a new message with that topic, the page will update automatically like magic.

With these approaches, you have no need to use VueJS so you don't need to load the vue and bootstrap libraries.

If, however, you DO want to use Vue for some reason, UIBUILDER also has you covered. In that case, you would need to transfer the content of your incoming message to a data variable managed by the VueJS framework. The name of that data variable would then be what you put in your {{....}}. The UIBUILDER template that references Vue has an example of doing that.

<div class="timerText"><uib-var variable="uibuilder.msg.timerText"></uib-var></div>

If I put this in the html file, nothing happens. Or do I have to do something more. I looked at the documentation, but this is chinees for me. Sorry?
I put an missing ">" after the msg.timerText .

The node before the uibuilder node is a function like:

msg.payload = global.get("savedata") || [];
msg.timerText = global.get("formattedTimeElapsed");
return msg;

The table shows on screen, the msg.timerText not.

Use the other method I shared. If necessary, you can send 2 messages instead of 1.

// Send the timer
node.send({payload: global.get("formattedTimeElapsed") ?? "", topic: "timer"});
// and send everything else
msg.payload = global.get("savedata") ?? [];
return msg;

Still no luck, only the table comes on screen. I checked the name "formattedTimeElapsed".
Do I still add something?

The function look like:

node.send({ payload: global.get("formattedTimeElapsed") ?? "", topic: "timer"});
msg.payload = global.get("savedata") ?? [];
return msg;

I put <div class="timerText" uib-topic="timer"></div>just after Scorebord
The html file looks like :

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <title>Scorebord</title>
    <meta name="description" content="Node-RED UI Builder - VueJS + bootstrap-vue default template" />

    <!-- <link rel="icon" href="./images/node-blue.ico" /> -->

    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />
    <!-- Your own CSS -->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all" />
  </head>
  <body>
    <h1>Scorebord</h1>
    <div class="timerText" uib-topic="timer"></div>
    <div id="app" v-cloak>
      <b-container id="app_container" class="mt-5">
        
        <div class="mt-5">
          <b-table striped hover small :items="items" ></b-table>
        </div>
      </b-container>
    </div>

    <!-- These MUST be in the right order. Note no leading / -->

    <!-- REQUIRED: Socket.IO is loaded only once for all instances. Without this, you don't get a websocket connection -->
    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>

    <!-- Vendor Libraries - Load in the right order, use minified, production versions for speed -->
    <script src="../uibuilder/vendor/vue/dist/vue.js"></script>
    <!-- dev version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.min.js"></script>   prod version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.runtime.min.js"></script>   prod version without component compiler -->
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
    <!-- Dev version -->
    <!-- <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.min.js"></script>   Prod version -->

    <!-- REQUIRED: Sets up Socket listeners and the msg object -->
    <script src="./uibuilderfe.js"></script>
    <!-- dev version -->
    <!-- <script src="./uibuilderfe.min.js"></script>     prod version -->

    <!-- OPTIONAL: You probably want this. Put your custom code here -->
    <script src="./index.js"></script>
  </body>
</html>

Let me do a quick test.

Woah, sorry, that html is well out of date. Are you using the current version of UIBUILDER - sorry I made an assumption that you were.

The code I gave you relates to the latest version of uibuilder and its current client library. What you've got there uses the old library which was deprecated in v6 and removed in v7. So there was well over 2 years to make the switch-over.

Best thing to do at this stage would be to make sure you have the latest version and make copies of your html and js files and then reset the template on the uibuilder node to be the default template (the simplest one to work with). That will give you a working baseline.

You can then add back in the bit of HTML that you need.

It is hard to update node-red-contrib-uibuilder, I get an error in the log.

-----------------------------------------------------------
2024-10-03T12:44:48.496Z Install : node-red-contrib-uibuilder 7.0.4

2024-10-03T12:44:48.813Z npm.cmd install --no-audit --no-update-notifier --no-fund --save --save-prefix=~ --production --engine-strict node-red-contrib-uibuilder@7.0.4
2024-10-03T12:44:49.692Z [err] npm
2024-10-03T12:44:49.692Z [err]  WARN config production Use `--omit=dev` instead.
2024-10-03T12:44:50.315Z [out] 
2024-10-03T12:44:50.315Z [out] up to date in 670ms
2024-10-03T12:44:50.332Z rc=0

The old node-red-contrib-uibuilder I can't remove nor enable nor update. That node is blocked in the user setting Nodes. If I try to update, the I get an error in the log. See above.

I'm so sorry to disturb you on this matter, but I losing my head .

It isn't a problem at all. I'm sorry you are having issues it is generally very stable.

You should note that what you've shared from the log is NOT an error but just a warning about the way that the Node-RED handles npm to install nodes. It isn't related to uibuilder at all.

Once you've done the update, a restart of Node-RED and reload the editor page should bring things back to normal but with the new version.

However, I can see that you have uibuilder v6.8.2 install which is good because you can, at least use <uib-var>. Let me work up an example using that.

OK, this should work with v6.8.2 or with v7

All I did was add a new uibuilder node with the default template. I added this HTML:

<div><uib-var topic="timerText">Waiting for data via a msg with the topic "timerText"</uib-var></div>

And I injected this:

That works fine.

I think I may have spotted a bug in the other method which isn't helping us. But this works.

If you manage to get uibuilder v7 installed, you can simplify things further by using this html:

<div uib-topic="timerText">Waiting for data with uib-topic="timerText"</div>

Thanks, But it is not working for me.
What did I do : I select a new inject and a new uibuilder node.
Schermafbeelding 2024-10-04 111400

I gave the uibuilder a name "outdoor" and I did'nt change the basic .css and the .js.


I add a line to .html

I change the inject properties like you suggested.
Schermafbeelding 2024-10-04 111420

and I get this onscreen, even after I push the inject node or refresh the browser.
Schermafbeelding 2024-10-04 112501

OK, not sure what is happening. Please try the following flow:

[{"id":"1c68e42899b4fdfc","type":"group","z":"ef122f0d.d488b","style":{"stroke":"#999999","stroke-opacity":"1","fill":"none","fill-opacity":"1","label":true,"label-position":"nw","color":"#a4a4a4"},"nodes":["275c7ed6844c6473","2ba99551e2e4aa59","4e5c278ae8ba963d","8177def783d3dd7b","f94187c0778ba2ca","4b1483ace9cd8606","6c23d6b86f812edd"],"x":114,"y":5079,"w":938,"h":248},{"id":"275c7ed6844c6473","type":"debug","z":"ef122f0d.d488b","g":"1c68e42899b4fdfc","name":"debug 2707","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":710,"y":5120,"wires":[]},{"id":"2ba99551e2e4aa59","type":"uibuilder","z":"ef122f0d.d488b","g":"1c68e42899b4fdfc","name":"","topic":"","url":"forum-pepe2","okToGo":true,"fwdInMessages":false,"allowScripts":false,"allowStyles":false,"copyIndex":true,"templateFolder":"blank","extTemplate":"","showfolder":false,"reload":true,"sourceFolder":"src","deployedVersion":"7.0.3","showMsgUib":false,"title":"","descr":"","editurl":"vscode://file/src/uibRoot/forum-pepe2/?windowId=_blank","x":540,"y":5120,"wires":[["275c7ed6844c6473"],[]]},{"id":"4e5c278ae8ba963d","type":"inject","z":"ef122f0d.d488b","g":"1c68e42899b4fdfc","name":"Toggle Visible Msgs","props":[{"p":"_uib","v":"{\"command\":\"showMsg\"}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":250,"y":5200,"wires":[["2ba99551e2e4aa59"]]},{"id":"8177def783d3dd7b","type":"inject","z":"ef122f0d.d488b","g":"1c68e42899b4fdfc","name":"topic=\"timerText\"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"timerText","payload":"\"via topic=timerText - \" & $random() * 100","payloadType":"jsonata","x":260,"y":5120,"wires":[["2ba99551e2e4aa59"]]},{"id":"f94187c0778ba2ca","type":"inject","z":"ef122f0d.d488b","g":"1c68e42899b4fdfc","name":"Log Lvl 0","props":[{"p":"_uib","v":"{\"command\":\"set\",\"prop\":\"logLevel\",\"value\":0}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":280,"y":5280,"wires":[["2ba99551e2e4aa59"]]},{"id":"4b1483ace9cd8606","type":"inject","z":"ef122f0d.d488b","g":"1c68e42899b4fdfc","name":"Log Lvl 5","props":[{"p":"_uib","v":"{\"command\":\"set\",\"prop\":\"logLevel\",\"value\":5}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":280,"y":5240,"wires":[["2ba99551e2e4aa59"]]},{"id":"6c23d6b86f812edd","type":"group","z":"ef122f0d.d488b","g":"1c68e42899b4fdfc","name":"Run this to update the front-end code files (after setting the uibuilder url name) \\n ","style":{"fill":"#ffffff","fill-opacity":"0.31","label":true,"color":"#000000"},"nodes":["fe5c700692183d1f","afc09228d3de702d","f94bd83566a97b69","f9d3f4a9160f4700"],"x":424,"y":5203,"w":602,"h":98},{"id":"fe5c700692183d1f","type":"inject","z":"ef122f0d.d488b","g":"6c23d6b86f812edd","name":"","props":[],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":485,"y":5260,"wires":[["f9d3f4a9160f4700"]],"l":false},{"id":"afc09228d3de702d","type":"template","z":"ef122f0d.d488b","g":"6c23d6b86f812edd","name":"","field":"payload","fieldType":"msg","format":"html","syntax":"mustache","template":"<!doctype html>\n<html lang=\"en\">\n\n<head>\n\n    <meta charset=\"utf-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n    <link rel=\"icon\" href=\"../uibuilder/images/node-blue.ico\">\n\n    <title>Update text via msg.topic - Node-RED uibuilder</title>\n    <meta name=\"description\" content=\"Node-RED uibuilder - Update text via msg.topic\">\n\n    <!-- Your own CSS (defaults to loading uibuilders css)-->\n    <link type=\"text/css\" rel=\"stylesheet\" href=\"./index.css\" media=\"all\">\n\n    <!-- #region Supporting Scripts. These MUST be in the right order. Note no leading / -->\n    <script defer src=\"../uibuilder/uibuilder.iife.min.js\"></script>\n    <!-- <script defer src=\"./index.js\">/* OPTIONAL: Put your custom code in that */</script> -->\n    <!-- #endregion -->\n\n</head>\n\n<body class=\"uib\">\n\n    <h1 class=\"with-subtitle\">Update text via msg.topic</h1>\n    <div role=\"doc-subtitle\">Using the uibuilder IIFE library.</div>\n\n    <div id=\"more\">\n        <!-- '#more' is used as a parent for dynamic HTML content in examples -->\n    </div>\n\n    <article>\n        <h2>Dynamic text using <code>uib-var</code> with <code>msg.topic=\"timerText\"</code></h2>\n        <div>\n            <uib-var topic=\"timerText\">Waiting for data via a msg with the topic \"timerText\"</uib-var>\n        </div>\n        <p>Should work with an version of uibuilder from v6+</p>\n    </article>\n\n    <article>\n        <h2>Dynamic text using <code>uib-topic</code> attribute on any tag</h2>\n        <div uib-topic=\"timerText\">Waiting for data with uib-topic=\"timerText\"</div>\n        <p>Should work with an version of uibuilder from v7+</p>\n    </article>\n\n</body>\n\n</html>","output":"str","x":760,"y":5260,"wires":[["f94bd83566a97b69"]]},{"id":"f94bd83566a97b69","type":"uib-save","z":"ef122f0d.d488b","g":"6c23d6b86f812edd","url":"forum-pepe2","uibId":"2ba99551e2e4aa59","folder":"src","fname":"","createFolder":false,"reload":true,"usePageName":false,"encoding":"utf8","mode":438,"name":"","topic":"","x":930,"y":5260,"wires":[]},{"id":"f9d3f4a9160f4700","type":"change","z":"ef122f0d.d488b","g":"6c23d6b86f812edd","name":"index.html","rules":[{"t":"set","p":"fname","pt":"msg","to":"index.html","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":5260,"wires":[["afc09228d3de702d"]]}]

I have tried this on both my development (Windows) and live (Debian Linux) servers and it is working correctly.

Import the flow. Set the uibuilder node's URL field (I used "forum-pepe2"). Set the uib-save node to the same name (using the drop-down). Click on "Deploy".

Then open the resulting page - which should show the "Blank" page. Then click on the inject for the template group. Then reload the page, you should see something like:

Then click on the topic inject and you should see something like:

Obviously, the 2nd box on the page will only have updated if you managed to update uibuilder to v7.

Hi, I found a working example on internet in 2 different parts. One to put the timer on screen and another one to show the tabel.


and the other screen is:

Seperate they are perfect but I don't find a way to put them together to have it on one screen.

Index.js file is for both screens the same like:

var app1 = new Vue({
    // The HTML element to attach to
    el: '#app1',
    // Variables defined here will be avalable and updated within the HTML
    data: {
        msg: '[No Message Received Yet]',
    },
    // Callback function when Vue library is fully loaded
    mounted: function () {
        // Start up uibuilder
        uibuilder.start();
        // Keep a reference to the Vue app
        var vueApp = this;
        // Callback triggered when node receives a (non-control) msg
        uibuilder.onChange('msg', function (msg) {
            vueApp.msg = msg;
        });
    },
});

"use strict";

const app2 = new Vue({
    el: "#app2",

    data() {
        return {
            items: []  // table data 

        };
    }, // --- End of data --- //

    computed: {}, // --- End of computed --- //

    methods: {}, // --- End of methods --- //

    // Available hooks: beforeCreate,created,beforeMount,mounted,beforeUpdate,updated,beforeDestroy,destroyed, activated,deactivated, errorCaptured

    /** Called after the Vue app has been created. A good place to put startup code */
    created: function () {
        // Example of retrieving data from uibuilder
        this.feVersion = uibuilder.get("version");

        uibuilder.start();
    }, // --- End of created hook --- //

    /** Called once all Vue component instances have been loaded and the virtual DOM built */
    mounted: function () {
        //console.debug('[indexjs:Vue.mounted] app mounted - setting up uibuilder watchers')
        // Start up uibuilder
        
        var app2 = this; // Reference to `this` in case we need it for more complex functions
        
        // If msg changes - msg is updated when a standard msg is received from Node-RED over Socket.IO
        uibuilder.onChange("msg", function (msg) {
            console.info('[indexjs:uibuilder.onChange] msg received from Node-RED server:', msg)
            app2.items = msg.payload;  // save new table data from node-red in vue data items

        });


    }, // --- End of mounted hook --- //
}); // --- End of app2 --- //

// EOF

for the index.html file I put this for the timer in the body:

<h1>Scorebord</h1>
    <!-- The "app" element contains any content that receives dynamic updates -->
    <div id="app1">
        <div class="timerText1">Speeltijd</div>
        <div class="timerTijd1">{{msg.timerText1}}</div>
        <div class="strafText1">{{msg.Straftijd1}} minuten straftijd</div>
    </div>

Or I put this for the table in the body :

    <div id="app2" v-cloak>
        <b-container id="app_container" class="mt-5">
        
            <div class="mt-5">
                <b-table striped hover small :items="items"></b-table>
            </div>
        </b-container>
    </div>

The full index.html for the timer looks like:

<!DOCTYPE html>
<html lang="en">

<head>
    <title>Scorebord</title>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <meta name="description" content="Node-RED UI Builder - VueJS + bootstrap-vue default template" />

    <!-- <link rel="icon" href="./images/node-blue.ico" /> -->

    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap/dist/css/bootstrap.min.css" />
    <link type="text/css" rel="stylesheet" href="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.css" />
    <!-- Your own CSS -->
    <link type="text/css" rel="stylesheet" href="./index.css" media="all" />
</head>

<body>
    	
    <h1>Scorebord</h1>
    <!-- The "app" element contains any content that receives dynamic updates -->
    <div id="app1">
        <div class="timerText1">Speeltijd</div>
        <div class="timerTijd1">{{msg.timerText1}}</div>
        <div class="strafText1">{{msg.Straftijd1}} minuten straftijd</div>
    </div>

    <!-- The "app" element contains any content that receives dynamic updates -->
   
    

    <!-- These MUST be in the right order. Note no leading / -->

    <!-- REQUIRED: Socket.IO is loaded only once for all instances. Without this, you don't get a websocket connection -->
    <script src="../uibuilder/vendor/socket.io/socket.io.js"></script>

    <!-- Vendor Libraries - Load in the right order, use minified, production versions for speed -->
    <script src="../uibuilder/vendor/vue/dist/vue.js"></script>
    <!-- dev version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.min.js"></script>   prod version with component compiler -->
    <!-- <script src="../uibuilder/vendor/vue/dist/vue.runtime.min.js"></script>   prod version without component compiler -->
    <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.js"></script>
    <!-- Dev version -->
    <!-- <script src="../uibuilder/vendor/bootstrap-vue/dist/bootstrap-vue.min.js"></script>   Prod version -->

    <!-- REQUIRED: Sets up Socket listeners and the msg object -->
    <script src="./uibuilderfe.js"></script>
    <!-- dev version -->
    <!-- <script src="./uibuilderfe.min.js"></script>     prod version -->

    <!-- OPTIONAL: You probably want this. Put your custom code here -->
    <script src="./index.js"></script>
</body>

</html>

My knowledge is to low to understand the detail and put it to one working file.
Is there a possibility to get it in one working file?

No longer needed, please remove. Doesn't hurt but just gets in the way.

Yes, of course. But this is no longer to do with UIBUILDER. You don't need 2 Vue apps either. 1 app can do lots of things.

While I can help with UIBUILDER things, I'm afraid I don't have the time to help you learn HTML, CSS, JavaScript and VueJS.

What I can say is that you might find ChatGPT quite helpful to be able to stretch your knowledge. But there is no substitute for taking things 1 step at a time to learn I'm afraid.

If you are still struggling with the concepts in UIBUILDER, please work through the beginners walkthrough in the docs. There are some basic videos as well, also referenced in the docs.

1 Like

Thanks, I will have a look.

I've learned some stuff from Kevin in the past but he has a significant blind-spot in my opinion. He is so focused on teaching the latest-greatest CSS that he often forgets that, in the real-world, half the stuff he says to use is not universally in use. That even comes across in this video where he tries to catch out the models with cutting-edge features - you can't use most of those features yet if you care at all about a wide range of potential users. So a lot of his stuff will be really useful in a couple of years time! :slight_smile:

As for which AI tool. Google Gemini remains pretty rubbish.

Microsoft and/or GitHub CoPilot seems to cost far too much for me to stomach so I'll not be using them.

ChatGPT 4o gets plenty of stuff wrong but seems to usually give enough clues to be able to push forwards. I've used it a lot recently to help build some really powerful web components and it has taken days off the time to get things to a working state.

I was trying to remember whether I'd used Claude - I don't believe I have and I think that I've hit this "barrier" a couple of times:

WHY?!

Why does it want my PHONE NUMBER? And by birth-date? I already gave it a Google account. I'm not even sure that demanding these is even really legal under EU laws.

So no thanks, they don't need my phone number or birthdate and they aren't getting them.

2 Likes

I love Kevin's video's, but I haven't touched css for like 3 years, just use Tailwind, it is the best thing since sliced bread, and for tailwind itself I use a js library instead, that contains all utility classes just shy of 30KB. No build/compile steps, amazing stuff. Speeds up your development time 10 fold.

1 Like

I think the video shows out clearly both sides of AI helpfulness. I don't use it cos I have no need. But it may help to get things done. Still, many may find that tagging me works better. Wild world full of options.

3 Likes