Ui Builder Script to get output

Hello,

today i tryed the Ui builder and i have some nice Buttons that i tryed to use.
The Frontend works great but can someone help me how i send something to node red when i push a Button and how i can switch a Button from Node Red on and off?

Thx in Advance

html.txt (2.0 KB)

css.txt (2.2 KB)

index.js file :

/* eslint-disable strict */
/* jshint browser: true, esversion: 6, asi: true */
/* globals uibuilder */
// @ts-nocheck

/** Minimalist code for uibuilder and Node-RED */
"use strict";

// run this function when the document is loaded
window.onload = function () {
  // Start up uibuilder - see the docs for the optional parameters
  uibuilder.start();

  // select all buttons
  const buttons = document.querySelectorAll(".am__input");

  // add click event to all buttons
  buttons.forEach((elem) => {
    elem.addEventListener("click", (event) => {

      uibuilder.send({
        topic: `${event.target.id}`,
        payload: event.target.checked,
      });

    });
  });

  // Listen for incoming messages from Node-RED
  uibuilder.onChange("msg", function (msg) {
    console.info("[indexjs:uibuilder.onChange] msg received from Node-RED server:", msg);
  });
};

Explanation:

  1. select all buttons of .am__input class with querySelectorAll
  2. loop through all the elements and add a click event listener to them that
  3. executes a dynamic uibuilder send command with the id of the button as a topic and its state (true/false) if its checked or not

image

ps. something similar can be done for the reverse .. receiving a msg in uibuilder.onChange to toggle the button

1 Like

Couple of things to add to that.

Firstly, if using uibuilder v6, please think about switching to the "new" client library. Then you no longer need to load the socket.io library nor do you need uibuilder.start() and you get access to all the new goodies coming along. Including the improved version of uibuilder.eventSend(event).

Secondly, as indicated above, rather than attaching a standard uibuilder.send, you can use eventSend which gives you extended information such as whether the user was holding down a modifier key (ctrl, shift, ...) when they pressed the button, what page name it came from, etc. Saves you a whole bunch of work.

Have you looked at the examples that are included when you install uibuilder? Worth taking a look at. Also have a look through the standard templates since some of them include buttons already pre-configured for you.

As Andy has indicated, all you need is to add an onclick event handler that either is set to uibuilder.eventSend(event) or set to a function of your own that calls uibuilder.send({....}).

To do this, you need to change the button's disabled property to true/false.

uibuilder.onChange('msg', (msg) => {
   // You need something in the msg to identify what to do
   if (msg.topic === 'chg-button1') {
      // Assumes that your button has id="button1"
      $('#button1').disabled = msg.payload
   }
})

Final note - if you were to use the new client library uibuilder.iife.min.js in place of the older uibuilderfe.min.js, you could also make use of the low-code capabilities. In that case, you can send a special message from Node-RED without the need for any code in the front end. For example, this should disable a button.

msg._ui = [
    {
        "method": "update",
        "components": [
            {
                // The type prop lets you use a CSS Selector, this will disable all buttons.
                // Alternatively set to `#myid` or some more complex selector as needed.
                "type": "button",
                "properties": {
                    "disabled": true
                }
            }
        ]
    }
]

Obviously, you could set that up with a simple change node set to JSONata can make the true/false part taken from payload: "disabled": payload.

1 Like

@UnborN @TotallyInformation

Thx for the Help.

with that index.js it is Working and i was albe to use it also on a slider that he gives out the value between 0-100

With the new Library i got some glitches in my css need to look why that happens.

But iam not able to trigger the Slider or Button from Node Red.

can u help me with an Example?

The Sliders Id is "Brighness" an i also used class="am__input"

When i wanne set the Slider now to 80 do i need a function node where i put the Id and the Value or where can i send the Value to the uibuilder ?

Here is the Slider Hmtl/CSS/JS:

html.txt (1.1 KB)
css.txt (2.1 KB)
js.txt (958 Bytes)

Ah, it might be forcing a load of an extra CSS file - check your network tab in browser dev tools for a CSS file load you didn't expect. I can't remember whether I fixed that in v6.0 or not. I thought I had though.

To change any input tag from node-red using the new client library, you can use the msg._ui low-code feature. To change your specific slider, this should work. Send a message with msg._ui set to this:

[
    {
        "method": "update",
        "components": [
            {
                "id": "Brightness",
                "properties": {
                    "value": 80
                }
            }
        ]
    }
]

No client-side code needed. To make it easy to set to any value based on the payload of an incoming message, you can use a change node. Try this partial flow:

[{"id":"29515e346307ce01","type":"change","z":"c51f51da7ee02d68","name":"","rules":[{"t":"set","p":"_ui","pt":"msg","to":"[\t    {\t        \"method\": \"update\",\t        \"components\": [\t            {\t                \"id\": \"Brightness\",\t                \"properties\": {\t                    \"value\": payload\t                }\t            }\t        ]\t    }\t]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":350,"y":2040,"wires":[["59ced185ee899b64"]]},{"id":"233719e10e85b81b","type":"inject","z":"c51f51da7ee02d68","name":"","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"80","payloadType":"num","x":190,"y":2040,"wires":[["29515e346307ce01"]]}]

Ah Thx a lot that Works fine.

When i use the new Library i find this css File that did not show up with the Old one:

2css

uib-brand.css

I guess i cant do anything agianst that behavior?

it seems to be loading those uib css files even if an existing user index.css is present

i remember you made some fixes for an issue i had with the loadStylesheet: false option .. dont know if its related

Just check to make sure that you aren't manually loading that in the index.css file - it may still contain the line: @import url("./uib-brand.css");. If it does, comment it out.

Otherwise, the quickest workaround would be to copy the front-end/uibuilder.iife.min.js file from the v6.1.0 branch on GitHub to your installed version of uibuilder.

What is supposed to happen is that if you haven't loaded any CSS at all, the uibuilder client will auto-load the brand-css file.

node-red-contrib-uibuilder/uibuilder.module.js at main · TotallyInformation/node-red-contrib-uibuilder (github.com)

If you put uibuilder.logLevel = 3 at the start of your index.js file, you should be able to spot what is happening by searching for the log messages shown in the link above.

Hopefully it is just your index.css file loading the brand css. If not, let me know and I'll see if I can get a bug-fix release out for v6.0.

I cleared the CSS File completly before Adding the new CSS for the Buttons.

Sorry to mess you about but can you try putting each of these two commands into your browser's dev tools console for the page please and let me know what they output?

document.styleSheets.length
document.styleSheets[0].cssRules.length

Also, try putting a dummy style into the index.css file, something like:

.mydummy {color:red;}

will do it.

That would - should - take the document.styleSheets[0].cssRules.length to >0 which should stop the brand css from loading.

Like that ? or where do i need to put it ?

Also theres a failure.

Well interesting. Thanks for that. But it is saying that it ISN'T loading that stylesheet! But of course, it is!

I've now had a chance to check on my test systems. I can see that the problem is still existing in v6.0 but has been fixed in the upcoming v6.1

So, here is the cheeky workaround. :astonished:

Create a completely blank new css file in the same folder as index.css and load it in your `index.html.

I did this all from the uibuilder node. First I created an empty index1.css file
image

Then I loaded it in the html

That will do the trick and it really won't impact your app. You will be able to tidy it up when v6.1 is out.

1 Like

Yes like that it Works, thx a Lot for all the Help !

1 Like

Hi, i just run in to an Problem.

The Slider iam Using, Today i had some Time and i wanted to integrate it to my Dashboard and then i find out that It wont work with my Touch Display. I have an Little Pc something like an Nuc that runs Debian 11 with an Touch Monitor where My Dasboard is running.

When i run the Site with the Silder and i touch on it it doesnt Work but when i Click on it with my Mouse it Works and gives an output to Node Red. I also have an Windows PC where it Works with my Mouse and on my Android Pghone it also doesnt Work with the Touch Funktion.

Do i need to set something special in the Script that it is useable with the touch funkion?

Edit:

I use IO Broker and embedded the Slider there in a other Site, can that cause the Problem?
Before i always used this Method for html/css for Node Red and there it always worked like that

Front-end Website with Node-RED: Example Form (flow) - Node-RED

Edit 2:

Ok it sems the Problem is the Slider with the other Html/Css Nodes i got the same Problem

Just to be clear - are you using a uibuilder page embedded into a Node-RED Dashboard? If so, have you tried the page stand-alone?

I'm sorry, but I'm not following that. What is "IO Broker"?

I think you will need to share some code.

uibuilder itself does not do any special handling for touch. Some of the examples and templates have an on-click handler as an example for a button. But if you are using a slider on a uibuilder page with v6.0, no special touch handlers are defined - it would be down to whatever your browser does.

However, I believe that Dashboard, which uses AngularJS, does do some touch handling. So maybe an embedded page in Dashboard might inherit something?

So now i found out this behavior only apears in Chromium Browser when i use Firefox it works normaly.

Its rly weird since when i push on it with my Finger the slider is moving like it should but thers just no output to NodeRed , but when i use my Mouse and click on it i get an output.

I cheked it with the embededd Page and also i loaded the Slider diretcly in Chromium same result.

flows (6).json (4.8 KB)

This is the Code for the Slider but i think thats a Problem that Chromium got.

Hi, can you reply to my other questions? That way, we may be able to get to the bottom of it. Thanks.

Just to be clear - are you using a uibuilder page embedded into a Node-RED Dashboard? If so, have you tried the page stand-alone?

I'm sorry, but I'm not following that. What is "IO Broker"?

Not an Node Red Dashboard but an Dasboard from IoBroker what is basicly something like Home Assistant.

I tryed it Standalone and it behaves the same like embendded.

Iam Using Chromium on Debian 11 i also upgraded the system today.

On my Android phone it also doesnt Work, but i tryed on an I phone just now with Safari and Google Chrome and there it is working. Standalone or emedded both works

OK, thanks for that, makes it a bit clearer but not sure what is going on.

Is that not a standard input range field? I just built a quick form with an input range field and it worked fine on Edge for Android which is based on Chromium.

i tryed now with Opera Edge Chromium and Firefox it only works with Firefox.

and you get the value output in Node Red? can you show me the Html/Css/Js from your simple slider so i can check if that works here.