# Second Stage of navigation?

**URL:** <https://discourse.nodered.org/t/second-stage-of-navigation/86713>\
**Category:** Dashboard\
**Tags:** uibuilder\
**Created:** [24 March 2024 11:18 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713 "2024-03-24T11:18:55Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![David83](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/david83/32/89387_2.png) [@David83](https://discourse.nodered.org/u/David83)\
**Post date:** [24 March 2024 11:18 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713/1 "2024-03-24T11:18:55Z")

</div>

I have cerate a routing in uibuilder like this:

_index.js_

```auto
// @ts-nocheck
/*globals UibRouter, uibuilder */

const routerConfig = {
    routeContainer: '#routecontainer',
    defaultRoute: 'lights',
    hide: true,
    routes: [
        {
            id: 'lights', src: './routes/lights.html', type: 'url',
            title: 'Lights'
        }, {
            id: 'power', src: './routes/power.html', type: 'url',
            title: 'Power'
        }
    ],
};

const router = new UibRouter(routerConfig)

```

_index.html_

```auto
<nav id="nav-standard">
        <a href="#lights" onclick="router.doRoute(event)" id="b-one">Lights</a>
	<a href="#power" onclick="router.doRoute(event)" id="b-two">Power</a>
</nav>
.
.
.

<div id="uibroutecontainer"><!-- router content will appear here --></div>

```

now i want a seconde stage of routing inside this pages, like _node-red.local:1880/lights/livingroom_ and _node-red.local:1880/lights/kitchen_.

Can anyone tell me the best way to implement this or recommend a tutorial where it is explained?

---

<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:** [24 March 2024 13:00 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713/2 "2024-03-24T13:00:18Z")

</div>

The router capability of UIBUILDER is still fairly new and therefore services the most common use-cases, it wasn't designed (yet) as a fully comprehensive multi-layer router. I suspect that, for that, you might need a far bigger and more complex router solution?

At present, only a single router instance is allowed on a page as well since trying to allow for multiple routers was more complex than I had time for when I put together the router library.

So right now, I think you have a number of potential workarounds:

- Flatten your routes by replicating, say, the outer HTML of the lights route across each room route html, then you only need 1 level of route.
- Go a non-route method for the rooms - which is what you would have done without a client-side router solution. For example, using a tabbed style layout where you hide or `display:none` the rooms you don't want to see.
- Create your own sub-router, dynamically loading and unloading the template like the router library does.
- Rummage through the current router library and see if either:
  - You can work out how to allow multiple router instances - I'd be more than happy either for a PR or for some hints on what needs changing. Noting that I am currently working on UIBUILDER v7 which contains a few potentially breaking changes (for a few people) and so that is an ideal time to do an uplift on the router as well.
  - Or whether you can work out how to do mutli-level routes.

---

<div class="post-metadata">

**Author:** ![David83](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/david83/32/89387_2.png) [@David83](https://discourse.nodered.org/u/David83)\
**Post date:** [31 March 2024 14:42 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713/3 "2024-03-31T14:42:18Z")

</div>

Thanks for the information @TotallyInformation !!!

For the moment i think i will use the non-route solution. I am not so firm in javasript that I could implement my own subrouter.

But I don't think multiple router instances are necessarily needed for nested routing. Nested routing can also be solved using an instance by specifying the sub-routes within the main routes.

Starting from such a configuration:

```auto
const routerConfig = {
    routeContainer: '#routecontainer',
    routes: [
        {
            id: 'lights', src: './routes/lights.html', type: 'url',
            title: 'Lights'
            subrouteContainer: '#lights-container' 
            subroutes: [
                {
                    id: 'lights/kitchen',
                    src: './routes/lights-kitchen.html',
                    type: 'url',
                    title: 'Kitchen',
                },
                { ... }
        }, 
    ],
};

```

Of course, it is then necessary to adapt the router logic accordingly and possibly the handling of the navigation events, or am I seeing this wrong?

---

<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:** [31 March 2024 16:45 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713/4 "2024-03-31T16:45:35Z")

</div>

Hi David,

That was my other thought as well. I will certainly add it to the backlog since it would make the router more powerful and probably doesn't need that much extra logic.

At present though, I'm focused on trying to get UIBUILDER v7 ready. Going reasonably well but, as usual, while doing something yesterday I spotted a bit of a logic fail in the startup code for managing the front-end libraries. I believe I have a better solution so that's the next task.

---

<div class="post-metadata">

**Author:** ![shrickus](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/shrickus/32/517_2.png) [@shrickus](https://discourse.nodered.org/u/shrickus)\
**Post date:** [1 April 2024 13:04 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713/5 "2024-04-01T13:04:09Z")

</div>

> [@TotallyInformation](#):
>
> At present, only a single router instance is allowed on a page as well since trying to allow for multiple routers was more complex than I had time for when I put together the router library.

Hmmm, so is that why UIB complains when I try to use a `/` in the root URL?  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/a/e/ae401da3da5a5137ac9b9c5d2a403ec64303f8a3.png)

Ideally I like to use the first part of the url e.g. `/fhir` to be the router for all urls used in the "FHIR" application -- then serve all the UI pages under `/fhir/ui/*` and set up `http in` nodes at `/fhir/api/*` for the backend api processing (since in this case I'm not using your built-in api router).

In fact, I'd love to be able to use a mix of the backend `api.js` router and `http in` flow apis -- but I suppose at best that would cause unpredictable results with multiple routes using the same root, right?

---

<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:** [1 April 2024 19:54 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713/6 "2024-04-01T19:54:26Z")

</div>

> [@shrickus](#):
>
> Hmmm, so is that why UIB complains when I try to use a `/` in the root URL?

No. But that has always been the case. What you are looking at there is something core to uibuilder itself rather than the front-end router library.

UIBUILDER has never allowed you to create a URL with a `/` as it would seriously mess up the ExpressJS server routing.

However, you can create FOLDERS in your front-end code folder and put more html files in there which gives a similar effect.

You can also set up uibuilder instance ExpressJS ROUTERS - these are specific to a uibuilder node and let you create dynamic routes at the server end rather than at the client end. You use the `<instanceRoot>/routes` folder for that. This feature was introduced in v6.5. Foolishly though, it looks like the only documentation for that is [in the release note](https://totallyinformation.github.io/node-red-contrib-uibuilder/#/changelog?id=new-features). You can also add instance-level ExpressJS middleware as well using the same feature. Another feature that allows is server-side html templating - using ExpressJS's templated view options.

> [@shrickus](#):
>
> Ideally I like to use the first part of the url e.g. `/fhir` to be the router for all urls used in the "FHIR" application -- then serve all the UI pages under `/fhir/ui/*` and set up `http in` nodes at `/fhir/api/*` for the backend api processing (since in this case I'm not using your built-in api router

A couple of ways to achieve that. Either use a reverse proxy (which should really always be your first port of call for doing complex URL, security, etc configurations). That will let you move whatever you like to wherever you like. If you need to separate all that out from Node-RED's native user URL's, you can always use a custom ExpressJS server as well - configure that in the uibuilder section of settings.js.

Or, if you don't mind Node-RED's core http-in nodes also getting the same URL prefix, simply change your `httpNodeRoot` in settings.js.

You can serve instance-level API's as well as server-side custom routes for your uibuilder node as mentioned above. API's have been available for a while and use the `<uibInstanceRoot>/api/` folder.

> [@shrickus](#):
>
> In fact, I'd love to be able to use a mix of the backend `api.js` router and `http in` flow apis -- but I suppose at best that would cause unpredictable results with multiple routes using the same root, right?

Well, that's one of the main reasons UIBUILDER is fairly strict about URL naming. Because ExpressJS allows multiple routes to serve the same URL, yes it can become a nightmare to manage and debug.

However, you absolutely should be able to do what you want. For example, you could serve an API using http-in/-out nodes at `/myurl/myapi` and have a uibuilder node with a name of `myurl`, that absolutely should (probably!) work. 🙂

Alternatively, you can have your `myurl` uibuilder node and use `~/.node-red/uibuilder/myurl/api/` and define your own ExpressJS API JavaScript file if you don't mind defining your own ExpressJS middleware. The required functions are native ExpressJS routes. Similarly, you can create generic server-side routing in `~/.node-red/uibuilder/myurl/routes/`. The functions you create are actually the same type.

---

<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:** [1 May 2024 19:54 UTC](https://discourse.nodered.org/t/second-stage-of-navigation/86713/7 "2024-05-01T19:54:55Z")

</div>

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