# How to create a sidebar tab

**URL:** <https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731>\
**Category:** Dashboard\
**Created:** [11 September 2020 07:23 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731 "2020-09-11T07:23:08Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [11 September 2020 07:23 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/1 "2020-09-11T07:23:08Z")

</div>

Hi, I currently want to create a tab in the sidebar, but I have a hard time.

If you look at the sidebar on the right side of Node Red, there is a dashboard button.  
The button contains a tab(layout, site, theme), and I want to create an additional tab.  
If anyone knows, I'd appreciate it if you let me know.

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [11 September 2020 08:05 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/2 "2020-09-11T08:05:54Z")

</div>

Hi Jisu,  
Some time ago I created a sidebar tab, and indeed it was not easy the first time ...  
Will try to find some time tonight to describe the basic steps, if nobody else has done it meanwhile...  
Bart

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [11 September 2020 08:09 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/3 "2020-09-11T08:09:04Z")

</div>

Hi @zl2su

can you describe a bit more what you want to do with the sidebar you wish to create?

You mention the dashboard sidebar with its layout/site/theme tabs. You say you want to add an additional tab - do you mean you want to add an extra tab to the dashboard sidebar (next to the layout/site/theme tabs), or a new sidebar entirely (like we have the Debug/Info/Help/Dashboard tabs)?

---

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [11 September 2020 10:10 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/4 "2020-09-11T10:10:54Z")

</div>

oh, thanks for responding.

I want to add a new sidebar entirely (like we have the Debug/Info/Help/Dashboard tabs).  
In fact, I want to make both later.

---

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [11 September 2020 10:11 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/5 "2020-09-11T10:11:27Z")

</div>

oh really? Thank you

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [11 September 2020 10:29 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/6 "2020-09-11T10:29:46Z")

</div>

It isn't documented, but you can see how the existing tabs are added if you search through the source code for `RED.sidebar.addTab`.

For example, here is where the Info sidebar tab is added: [https://github.com/node-red/node-red/blob/master/packages/node\_modules/@node-red/editor-client/src/js/ui/tab-info.js#L110](https://github.com/node-red/node-red/blob/master/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js#L110)

---

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [11 September 2020 10:54 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/7 "2020-09-11T10:54:20Z")

</div>

Oh, thank you

But, can I change the location of the input and output ports in the html file?

---

<div class="post-metadata">

**Author:** ![knolleary](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/knolleary/32/3_2.png) [@knolleary](https://discourse.nodered.org/u/knolleary)\
**Post date:** [11 September 2020 11:33 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/8 "2020-09-11T11:33:49Z")

</div>

> [@zl2su](#):
>
> can I change the location of the input and output ports in the html file

No, you cannot customise the appearance of a node without changing all of the editor code directly.

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [11 September 2020 22:27 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/9 "2020-09-11T22:27:28Z")

</div>

> [@BartButenaers](#):
>
> Some time ago I created a sidebar tab, and indeed it was not easy the first time ...  
> Will try to find some time tonight to describe the basic steps

Hey Jisu,

I have only create one sidebar node (see [node-red-contrib-xterm](https://github.com/bartbutenaers/node-red-contrib-xterm)) until now, and that is already quite some time ago. So I might have forgotten some stuff, but I'm sure others will correct me where needed ...

Some facts about such a sidebar tab:

- It depends on a single configuration node.

- Keep in mind that the user can remove that config node without you knowing it.  
_**[EDIT]**_ For example the config node of my xterm terminal sidebar can be found here:

- So you need to ensure that there exist always a single instance of that config node. Which means you have to create that config node instance (if it doesn't exist yet) in the following cases:

- For a normal node you only have to specify one single data template, which specifies how the (config) node's config screen looks like. However now you will have to specify extra a second data template, to specify how the sidebar panel looks like.

The javascript file looks rather similar to that of a normal node, but the html file is a bit different (based on the list of facts we just described). Below you can find an example of an html file, with lots of explanation inside. This code might contain syntax/logical errors, but it is just to give you an idea of how I think it works:

```auto
<script type="text/javascript">    
    (function ($) {
        // Keep a reference to the config node, the last time you have found it ...
        var myConfigNode = null;
        
        // Function to ensure that a single instance of myConfigNode (still) exists.
        // Call this function always before you try to access the config node!!!!
        // Caution: this function cannot be called from onpaletteadd, because then the RED.nodes are not filled yet!!!
        function ensureMyConfigNodeExists() {
            // If we have found the config node previously, check if it has been deleted by the user meanwhile
            if (myConfigNode !== null) {
                var configNode = RED.nodes.node(myConfigNode.id);
                if (configNode === null) { myConfigNode = null; }
            }
                
            // If not found previously, check if it has been created meanwhile
            if (myConfigNode === null) {
                var configNodes = [];
                RED.nodes.eachConfig(function(configNode) {
                    if (configNode.type === 'my_unique_config_node_name') { 
                        configNodes.push(configNode); 
                    }
                });
                
                // Make sure we only have 1 config node
                while (configNodes.length > 1) {
                    var configNode = configNodes.pop();
                    RED.nodes.remove(configNode.id);
                    RED.nodes.dirty(true);
                }
                
                // When we found a config node, let's use that one
                if (configNodes.length === 1) { myConfigNode = configNodes[0]; }
            }
            
            // When the config node doesn't exist yet, let's create a new instance of it
            if (myConfigNode === null) {
                myConfigNode = {
                    // Ask Node-RED to generate a new unique node id for your new config node
                    id: RED.nodes.id(),
                    // Ask Node-RED the type of your node
                    _def: RED.nodes.getType("my_unique_config_node_name"),
                    // Specify your node type
                    type: "my_unique_config_node_name",
                    // This config node is not used by another node, so it will appear with status "unused" in the "config nodes" sidebar.
                    // But that is very confusing, since the config node is used by your sidebar screen.
                    // To solve that set 'hasUsers' to false (see https://github.com/node-red/node-red/blob/master/CHANGELOG.md#0161-maintenance-release).
                    // Note that the 'hasUsers' needs also to be specified in the RED.nodes.registerType statement!
                    hasUsers: false, 
                    users: [],
                    label: function() { return this.name || "My node label"},
                    name: "My node name",
                    // Specify here all your config node properties here (with their default values)
                    // ...
                }
                
                // Add the new config node to the collection of Node-RED nodes
                RED.nodes.add(myConfigNode);
                
                // Make sure the "Deploy" button becomes active, by letting Node-RED know that something has changed
                RED.nodes.dirty(true);
            }
        }
        
        function sidebarResizeEventHandler() {
            // Resize the widgets inside your sidebar screen if required
		}

        RED.nodes.registerType('my_unique_config_node_name', {
            category: 'config',
            hasUsers: false,
            defaults: {
                name: { value: "My default node name" }
                // Specify here again all your config node properties (with the same default values as above)
                // ...
            },
            paletteLabel: 'My node palette label',
            label: function () {
                return this.name;
            },
            onpaletteremove: function () {
                // Remove the sidebar with id = sidebar-mysidebarname (which we have added a few lines further ...)
                RED.sidebar.removeTab("sidebar-mysidebarname");
                RED.events.off("sidebar:resize", sidebarResizeEventHandler);
            },
            onpaletteadd: function () {                
                // The html content of the sidebar page has been specified a a data-template, from where it can be loaded:
                var htmlContent = $($('script[type="text/x-red"][data-template-name="my_unique_config_node_name_sidebar"]').i18n().html());
                
                // Add a new "MySidebarName" tabsheet to the right sidebar in the flow editor, where you show the html content
                RED.sidebar.addTab({
                    id: "sidebar-mysidebarname",
                    label: "mysidebarlabel",
                    name: "MySidebarName",
                    content: htmlContent,
                    closeable: true,
                    disableOnEdit: true,
                    // Select here your own FontAwesome icon that needs to be displayed on the tabsheet in the sidepanel
                    iconClass: "fa fa-terminal"
                });
                
                RED.events.on("sidebar:resize", sidebarResizeEventHandler);
                
                // Here you can now initialise and setup your sidebar screen.
                // For example suppose that a value is changed in your sidebar panel, you might want to update that value in your config node.
                $("#some_element_id").on("change", function() {
                    // As said before, make sure your config node instance exists!
                    ensureMyConfigNodeExists();
                
                    // myConfigNode will point to your config node instance, so you can start manipulating it ...
                    myConfigNode.someProperty = "someValue";

                })            
            }            
        });
    })(jQuery);
</script>

<!-- YOUR FIRST DATA TEMPLATE TO DISPLAY THE CONFIG SCREEN WHEN THE CONFIG NODE IS DISPLAYED -->
<script type="text/x-red" data-template-name="my_unique_config_node_name">
    <div class="form-row">
        <label for="node-config-input-name"><i class="icon-tag"></i> Name</label>
        <input type="text" id="node-config-input-name" class="xterm-setting" placeholder="Name">
    </div>

    <!-- Add here a form-row for every input field that needs to be displayed in the sidebar-->
     
</script>

<!-- YOUR SECOND DATA TEMPLATE TO DISPLAY IN THE RIGHT SIDEBAR -->
<script type="text/x-red" data-template-name="my_unique_config_node_name_sidebar">
    <div style="position: relative; height: 100%;">
        <div style="position: absolute; top: 1px; bottom: 2px; left: 1px; right: 1px; overflow-y: scroll; padding: 10px;"> 
            <form class="dialog-form">
                
                <!-- Add here the html elements that needs to be displayed inside your sidebar panel -->
                
            </form>
        </div>
    </div>
</script>

<!-- YOUR INFO PANEL WITH HELP INFORMATION -->
<script type="text/x-red" data-help-name="my_unique_config_node_name">
    <p>Define here the html that needs to be displayed in the info sidebar panel.</p>
</script>

```

Hopefully this makes a bit clear how it works, so you can get started with your development...

Good luck with it!!  
Bart

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [12 September 2020 06:40 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/10 "2020-09-12T06:40:06Z")

</div>

> [@BartButenaers](#):
>
> `Caution: this function cannot be called from onpaletteadd, because then the RED.nodes are not filled yet!!!`

I see now there is an issue with my code snippet above...

Depending on my code comments from the time being, it is not possible to call the `ensureMyConfigNodeExists` in the `onpaletteadd` event. But that wasn't an issue for my xterm sidebar node, because my sidebar panel screen also contained two tabsheets.

- In the first tabsheet I didn't need the config node (and the data stored in it):

- But as soon as you clicked the second tabsheet I called - via the tab change event - the `ensureMyConfigNodeExists` function to show the config data:

But I'm not sure how you have to do it when there is only one screen on your tabsheet. If I remember correctly, you have no tab switch event to call custom code at the moment that your tabsheet becomes visible (where you can call the `ensureMyConfigNodeExists` function to get the config node data and show it into your sidebar panel screen). I'm not sure anymore about that.

**[EDIT]** I mean that I'm not sure if something like this is possible:

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/c/5c97c01b8ced59d0b4d490f0b18cdfed7838137b.png)

So would be nice if somebody could step in here to explain how to solve this!

---

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [12 September 2020 07:19 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/11 "2020-09-12T07:19:35Z")

</div>

Thank you so much, I am crying for your kind explanation.  
I have succeeded in adding a sidebar tab and creating the content of the sidebar tab.

However, it was difficult to create tabs in tabs (terminal\_xterm \>\> terminal, settings),  
so I used 'script' now.

I'm referencing the xterm code you made, and you created a detail tab using "globalTabsheets.addTab", but it doesn't work out when you use it.  
Is it correct to create and use globalTabsheets?  
Could you tell me if there is any other way?

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [12 September 2020 19:06 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/12 "2020-09-12T19:06:34Z")

</div>

> [@zl2su](#):
>
> I'm referencing the xterm code you made, and you created a detail tab using "globalTabsheets.addTab", but it doesn't work out when you use it.  
> Is it correct to create and use globalTabsheets?

Hi, was not online today ...  
Did you make any progress meanwhile?

> [@zl2su](#):
>
> but it doesn't work out when you use it

What exactly doesn't work out?

> [@zl2su](#):
>
> Could you tell me if there is any other way?

Another way to achieve what exactly? Be aware that we don't know anything about what you are trying to achieve ...

The `globalTabsheets` are the tabsheets within my sidebar screen:

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/c/9/c9d92f796a522cde27dbfff35af1d1474b43d7e0.png)

I don't know whether you need tabsheet inside your sidebar? If not, then you can ignore that part of my code.

---

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [14 September 2020 02:33 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/13 "2020-09-14T02:33:50Z")

</div>

Oh my god, i'm so sorry  
Yes, a lot of progress has been made thanks to your code.

You used globalTabsheets to put tab sheets in the sidebar as shown.  
So I also declared globalTabsheets to use globalTabSheets and did globalTabsheets.addTab, but it does not run.

I've currently made it like this using html code.

![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/f/d/fd9820299d23a5338453fb2041f200325cca94bf.png)

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [14 September 2020 05:15 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/14 "2020-09-14T05:15:06Z")

</div>

> [@zl2su](#):
>
> but it does not run

Yes but what do you mean with this? Does the content of those tabsheets not appear? Or is there another problem with it?

---

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [14 September 2020 06:14 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/15 "2020-09-14T06:14:51Z")

</div>

Oh~ Sorry, I think I did the wrong explanation.

This is your code.  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/b/9/b9989778f65cd7fd8ce818fc3106e458f8e1d233.png)

So, This is my code created by reference.  
 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/d/c/dc8a7962073b7afca17e1a0fc318cc2bbfdb9203.png)

GlobalTabsheets doesn't work. What am I writing wrong? 😭

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [14 September 2020 06:38 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/16 "2020-09-14T06:38:48Z")

</div>

What is the `gg.addTab` ?? Shouldn't that be `globalTabsheets.addTab` ?

---

<div class="post-metadata">

**Author:** ![zl2su](https://avatars.discourse-cdn.com/v4/letter/z/a587f6/32.png) [@zl2su](https://discourse.nodered.org/u/zl2su)\
**Post date:** [14 September 2020 07:00 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/17 "2020-09-14T07:00:53Z")

</div>

oh, My mistake..

Ignore the gg.tab because I just made it

When I run the code, the added content tab is not visible.

---

<div class="post-metadata">

**Author:** ![BartButenaers](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/bartbutenaers/32/10476_2.png) [@BartButenaers](https://discourse.nodered.org/u/BartButenaers)\
**Post date:** [14 September 2020 07:38 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/18 "2020-09-14T07:38:49Z")

</div>

If you can share a link to your Github repository, then people can have a look about what might go wrong. Otherwise it is nearly impossible to guess what could be the problem...  
You don't have any issues in your browser console log, I assume?

---

<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 October 2020 07:39 UTC](https://discourse.nodered.org/t/how-to-create-a-sidebar-tab/32731/19 "2020-10-14T07:39:03Z")

</div>

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