Uibuilder documentation suggestions and improvements

Thanks for that. Useful.

Just to note that for the next release, the list node is on its way to being deprecated - it was only ever marked as experimental. The new uib-element node replaces it and adds other outputs not just a list. The basic and default "Blank" template will be used in the examples for the new node and the blank template gets a make-over to make it even cleaner and simpler.

I'm sticking with the IIFE version of the client library though because ESM's are a fairly tough concept for beginners right now while JavaScript is still in transition. I expect this will change over time. But for now, it uses simpler, possibly more familiar concepts and is less restrictive - more forgiving perhaps. And more in line with the majority of HTML/JavaScript tutorials and training courses.

Even the list node should work just fine with the IIFE client version though. Or with the ESM version if that's your preference.

But none-the-less, a good point about ensuring the documentation for the new nodes is simple and clear.

Many thanks.

Thanks again for the guidance. After some thought, I agree with your assessment and I've replaced the introductory paras with pretty much your suggestion - though actually simplified a little more! The mention of frameworks is also a distraction so I'm removing that too. :grin:

I've also updated the home page of the documentation to match.

I'll also probably update the intro paras of the nodes themselves for clarity.

I realise that the Documentation (6.1.0) is 'early days', and these comments are supposed to be constructive from a 'newbie' point of view.

A couple/three of questions (using 6.1.0 version - using links in Github 6.1.0 Readme.md)

Will the 'First Timers walkthrough' documents be the same for 6.1, if so, I have no clue where this is,
You will also see a property called cacheControl with a value of "REPLAY". This can be wired back to the uibuilder input and used to send cached data when a new client connects (or an existing client reloads the page). Does that apply to 6.0 only?
(You also have Walkthough instead of Walkthrough)

Using the Example flows you gave, I have loaded into NR and am stuck on the Change the URL to match the base.

I am completely confused regarding the 'Parent' box for the uib-element node I have done HTML and CSS in the past, but I am not sure if it is my limited knowledge or the instructions baffling me.

Ah, needs a bit of a catch-up with the latest workflow :grin:
Fixed & simplified.

Thanks. Fixed.

Wow, how quickly things moved on! I should have updated that thread to say that you no longer need (or indeed want) to do that. In fact you can't because I took all of that complicated stuff out and threw it in the bin where it belonged.

Now, you simply take the output from the uib-element node and send it into a uibuilder node.

I've added a note to that thread.

OK, so this is a case of me struggling to find the right ways to help people understand.

One of the really important concepts to learn about HTML and CSS is that they are both hierarchical representations of a visual page. This is very strongly carried through into the low-code, standardised configuration data that the uib-element node actually creates. Think of it like pseudo-code, an intermediate description that can be converted reliably into HTML (referred to elsewhere as "hydration", a web-development technical term).

So with that in mind, an HTML page can be described as a family tree. Ancestors, parents, children, siblings.

So a "parent" represents the next higher-up step in the page hierarchy. The uib-element node lets you choose a parent element to attach your output to.

To make things a bit easier, all of the updated example flows and templates have something in the pre-defined page that looks like this:

<div id="more"><!-- '#more' is used as a parent for dynamic HTML content in examples --></div>

If you define a parent as #more, your output will be added as a new child of that div element. You can send many uib-element outputs to the same parent and each will add more new children one after the other.

Hope that clarifies things? If you can think of better and simpler ways to describe these concepts, please let me know.


PS: I should perhaps have also expanded on the CSS reference. You have various ways of identifying specific elements on a web page. The most common is now CSS Selectors. These are a standardised syntax for identifying anything. You can see them and copy them from existing pages using your browser's developer tools. In the case above, the leading # simply says look for an on-page element (or tag if you prefer that naming) with an id attribute of more. HTML id attributes must be unique on the page so they are reliable ways of grabbing a reference to a specific element.

Thank you @TotallyInformation, updated documents make more sense now (to me!).

I had a feeling it was my CSS knowledge that was letting me down. Limited experience, use Hugo for Websites now, so don't get involved in it anymore!! Thank you for the detailed explanation, immediately made sense and reminded me of what I had forgotten! (Seems to be the way with me these days!)

1 Like

None of us are getting any younger! I use an electronic "brain" to remember things. After many years of just using Microsoft OneNote, I've started moving my IT related stuff over to Obsidian which is an amazing and free tool and rather better suited to keeping snippets of code than OneNote is.

I will have a look.

Currently working through the instructions with my Pedant Head on, I will pick up things that probably don't matter, but would rather do that than miss something.

Github - Telegram works for you, not me. I am now 'Watching' uibuilder.

1 Like

Just wanted to say thankyou all for this very long and helpful thread.
I am still looking for a Node-RED dashboard replacement and after spending hours on uibuilder I still cant get it to work.... But I think its time I tried again perhaps. (And FlexDash needs a turn of my time as well).

I think @mudwalker summed it up really well several times, there is a gap between the art of the possible and the possible. I'm grateful for threads like this that try and close that gap.

I will continue to watch.

1 Like

Yes, definitely look at all options and weigh up the pros and cons. I may be a little biased towards uibuilder, can't think why! :grin:

I'm very grateful too. It is inevitable that documentation gets a bit muddled when you are the only one writing it. This kind of thread is exactly what is needed to take it to the next level. Time to force uibuilder to grow up!

I find that very sad and would really like to understand where things are going wrong so we can correct them for everyone else. It should be simple - and I think it is - but my brain isn't exactly the most linear of things so I regularly make things too complex.

Please do check out the re-written README referenced above. Obviously there will be references to some new nodes for v6.1 but the basics haven't changed other that in v6.1 and beyond, I'm now recommending a move from the old client library to the new one and updating all of the documentation, templates, and examples to match.

Possibly the walkthough and certainly the video will have been added since you last tried so those are also worth looking at.

For reference here are the getting-going steps:

  1. Install uibuilder
  2. Add a uibuilder node to a flow
  3. Open the settings and give it a url (the name that is used throughout)
  4. Deploy

You now have a working micro-site.

1 Like

Well i have just subscribed to your YT channel and pushed you past the 10 subscribers mark !!

You now have to drop everything and spend the next 30 days creating noteworthy content on the channel !

Looks good and much easier than the first time i tried.

Just cloning my current live environment in a new Dev VM and going to give it a whirl.

Craig

Wow, I'm well on my way to being able to monetise it! Not :rofl:

I think you are supposed to release every couple of days. Sorry, not happening! I do have another one in the pipeline though and a list of things I need to create videos for.

It has always been easy - just maybe not very well described :grin:

Feels like it is finally growing up though and about to enter a new phase. Thanks for trying it out and let me know if there is anything I can help with.

FYI - I also just installed, I have looked at it before but was also put off by docs as mentioned by others, (a bit intimating for us beginners).
Anyway I have managed to get a basic page working with some buttons.
I mangled the index,js to this -

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

        // dump the msg as text to the "msg.topic" html element
        var eMsg = document.getElementById(msg.topic)
        console.info('emsg:', eMsg)
        eMsg.innerHTML = (msg.payload)

But not sure if its the best / intended, way to update the page with my data, can you point me to idiots guide for displaying data from NR ?

That is certainly one way you can do it. One minor tweak you might find helpful. If you aren't using a library like old jQuery that already assigns the $ window variable, uibuilder assigns it itself but it uses the more generic document.querySelector(cssSelector) function.

So you can do:

const eMsg = $(`#${msg.topic}`)
if (eMsg) eMsg.innerHTML = msg.payload

Which you may find a bit easier to work with and is slightly more robust. You could also use innerText if you only want text and not HTML.

HOWEVER, you could also drive this from Node-RED directly by sending a message containing a msg._ui property containing this JSONata:

[
    {
        "method": "update",
        "components": [
            {
                "id": topic,
                "slot": payload
           }
        ]
    }
]

Here is a flow snippet that will do just that - it contains just an inject node with the data and a change node with the config. Hopefully enough for you to be able to expand it to your own needs.

[{"id":"a3d191ab9281d165","type":"inject","z":"225a6af5f8bc4cc2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"more","payload":"\"This is the dynamic number: \" & \t$formatInteger($random() * 100, \"0\")","payloadType":"jsonata","x":250,"y":860,"wires":[["ccbaf9391f9ea3bb"]]},{"id":"ccbaf9391f9ea3bb","type":"change","z":"225a6af5f8bc4cc2","name":"","rules":[{"t":"set","p":"_ui","pt":"msg","to":"[\t    {\t        \"method\": \"update\",\t        \"components\": [\t            {\t                \"id\": topic,\t                \"slot\": payload\t           }\t        ]\t    }\t]","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":430,"y":860,"wires":[["a176947e40e66640"]]}]

Also worth noting that when v6.1 gets released, this will be even easier because of the new node uib-update.

In addition, the msg._ui configuration schema lets you add and remove new HTML dynamically, not just update. At the end of this entry is a flow just containing a bunch of inject nodes that will show you the fun you can have. :slight_smile:

These methods have some other advantages too - they can be chained so you can build up a complex set up adds/removes/updates and send them all at once. You can also add a couple of helper libraries that allow the use of Markdown, not just sending text/html and that will sanitise any resulting HTML if you need to allow user input that might be abused.

Yes, please refer to the "First Timer's Walkthrough" in the documentation. However, please be patient because it is being reworked with the fine help of @mudwalker and should be a lot clearer in v6.1 - if you want to take an early look: https://github.com/TotallyInformation/node-red-contrib-uibuilder/blob/v6.1.0/docs/walkthrough1.md

Better still, if you can be bothered, try running up a test instance of Node-RED and install the uibuilder v6.1.0 branch into it. Then you can try out the new features and access the updated documentation directly.


Example flow snippet showing how you can create and manipulate HTML from Node-RED using uibuilder's low-code schema.

[{"id":"62d58bb53910ec63","type":"inject","z":"225a6af5f8bc4cc2","name":"Add List (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"remove\",\"components\":[\"#eltest-upd\"]},{\"method\":\"add\",\"components\":[{\"type\":\"ul\",\"id\":\"eltest-upd\",\"attributes\":{\"name\":\"testy-list\",\"style\":\"list-style: \\\"❌\\\";\"},\"components\":[{\"type\":\"li\",\"id\":\"eltest-upd-1\",\"attributes\":{\"data-row-index\":1,\"class\":\"odd\"},\"slot\":\"1) To do <span name=\\\"when\\\">now</span>\"},{\"type\":\"li\",\"attributes\":{\"data-row-index\":2,\"class\":\"even\",\"id\":\"eltest-upd-2\"},\"slot\":\"2) To do <span name=\\\"when\\\">tomorrow</span>\"},{\"type\":\"li\",\"id\":\"eltest-upd-3\",\"attributes\":{\"data-row-index\":3,\"class\":\"odd\"},\"slot\":\"3) To do <span name=\\\"when\\\">this week</span>\"},{\"type\":\"li\",\"id\":\"eltest-upd-4\",\"attributes\":{\"data-row-index\":4,\"class\":\"even\"},\"slot\":\"4) To do <span name=\\\"when\\\">sometime</span>\"}],\"parent\":\"#more\"}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":280,"wires":[["f3d45472d250833a"]]},{"id":"6b17d81ec2209b1d","type":"inject","z":"225a6af5f8bc4cc2","name":"Ambulance All (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"update\",\"components\":[{\"x-id\":\"eltest-upd\",\"name\":\"testy-list\",\"x-type\":\"ul\",\"x-parent\":\"#more\",\"attributes\":{\"style\":\"list-style: \\\"🚑\\\";\"}}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":150,"y":560,"wires":[["f3d45472d250833a"]]},{"id":"6b4d8a4a4ca96607","type":"inject","z":"225a6af5f8bc4cc2","name":"Overdue 1 (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"update\",\"components\":[{\"selector\":\"#eltest-upd *[data-row-index=\\\"1\\\"]:not([data-done=\\\"Y\\\"])\",\"attributes\":{\"style\":\"background-color: red; color: yellow; font-weight: bolder;\"}}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":140,"y":320,"wires":[["f3d45472d250833a"]]},{"id":"c47e58de8dc519b7","type":"inject","z":"225a6af5f8bc4cc2","name":"Tick off 2 (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"update\",\"components\":[{\"selector\":\"#eltest-upd > li:nth-child(2)\",\"# selector\":\"#eltest-upd *[data-row-index=\\\"2\\\"]\",\"# id\":\"eltest-upd-2\",\"attributes\":{\"style\":\"list-style: \\\"✅\\\";\",\"data-done\":\"Y\"}}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":400,"wires":[["f3d45472d250833a"]]},{"id":"7689357d95808fab","type":"inject","z":"225a6af5f8bc4cc2","name":"Tick off 1 (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"update\",\"components\":[{\"selector\":\"#eltest-upd > li:nth-child(1)\",\"# selector\":\"#eltest-upd *[data-row-index=\\\"1\\\"]\",\"# id\":\"eltest-upd-1\",\"attributes\":{\"style\":\"list-style: \\\"✅\\\";\",\"data-done\":\"Y\"}}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":360,"wires":[["f3d45472d250833a"]]},{"id":"cabe1f260b988cc2","type":"inject","z":"225a6af5f8bc4cc2","name":"Un-tick 1 (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"update\",\"components\":[{\"x-id\":\"eltest-upd-1\",\"selector\":\"#eltest-upd > li:nth-child(1)\",\"# selector\":\"#eltest-upd *[data-row-index=\\\"1\\\"]\",\"# id\":\"eltest-upd-2\",\"attributes\":{\"style\":\"list-style: revert;\",\"data-done\":\"N\"}}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":130,"y":440,"wires":[["f3d45472d250833a"]]},{"id":"56364793494b9db6","type":"inject","z":"225a6af5f8bc4cc2","name":"Chg Due 1 (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"update\",\"components\":[{\"selector\":\"#eltest-upd-1 > [name=\\\"when\\\"]\",\"slot\":\"soon\"}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":140,"y":480,"wires":[["f3d45472d250833a"]]},{"id":"050cc93892c1d90c","type":"inject","z":"225a6af5f8bc4cc2","name":"Chg Due all (_ui)","props":[{"p":"_ui","v":"[{\"method\":\"update\",\"components\":[{\"selector\":\"#eltest-upd *[name=\\\"when\\\"]\",\"# name\":\"when\",\"slot\":\"soonish\"}]}]","vt":"json"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":140,"y":520,"wires":[["f3d45472d250833a"]]}]
1 Like

Thanks will have a play later....

1 Like

I tried the example inject nodes, but the only thing that works is creating the list and changing the icons to ambulance. Nothing happened with the others ?

All the injects in this example work for me.

Have you updated to the most current version of V6.1.0?

There was a change in the uibuilder node earlier this week.

1 Like

The latest version in palette is 6.0, I thought these examples were for that version ?

If not how would I install latest dev - and do I need to remove existing version first ?

Sorry, I'm focused on 6.1 at the moment and I sometimes loose track of which version I'm working on :rofl:

To install the dev version, you need a command line on the server.

cd ~/.node-red
bon install totallyinformation/node-red-contrib-uibuilder#v6.1.0

Then restart node red and reload the editor window.

1 Like

OK examples are working now...thanks

1 Like

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