# Tutorial - create a sidebar plugin and persist the data in a config node

**URL:** <https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020>\
**Category:** Developing Nodes\
**Created:** [14 October 2023 07:24 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020 "2023-10-14T07:24:22Z")\
**Posts on this page:** 11\
**Page:** 2

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [16 October 2023 16:28 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/21 "2023-10-16T16:28:49Z")

</div>

Ok - Been following this thread for sometime.

@BartButenaers - Great tutorial 👍

One thing I find great for sidebar is the use of the stack panels & tree views!  
I use them in my ZWave plugin a fair bit

 ![Screenshot 2023-10-16 at 17.28.09](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/1/b/1be016ec8e02e0ee34060f0104c7df309901491b.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:** [16 October 2023 16:35 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/22 "2023-10-16T16:35:26Z")

</div>

Really nice layout 🤩

---

<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:** [16 October 2023 16:54 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/23 "2023-10-16T16:54:05Z")

</div>

> [@marcus-j-davies](#):
>
> stack panels & tree views

Are you building those by hand or using a library?

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [16 October 2023 16:58 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/24 "2023-10-16T16:58:57Z")

</div>

I do have a hint for sidebar - which may help others in easing the design  
I use [https://handlebarsjs.com](https://handlebarsjs.com) - to design the skeleton of the layout (1 in a million ways of course)

And use its JSON data processing features to fill in the data placeholders

A Breif example

`HTML Template` (held in a plugin html file)

```auto
<!-- Side Panel Template-->
<!-- prettier-ignore -->
<template id="TPL_SidePanel">
	<!--Network Selector-->
	<div class="red-ui-sidebar-header" id="zwave-js-network-header" style="display: none; text-align: center; height: 20px">
		<i class="fa fa-cog" aria-hidden="true"></i>
		Network/Runtime :
		<select id="zwave-js-network" onchange="NetworkSelected()" style="height: 25px; vertical-align: baseline">
			<option>Select Network</option>
                    {{#each Networks}}
                       <option value="{{this.id}}">{{this.name}}></option>
                    {{/each}}
		</select>
	</div>
</template>

```

`JS` - loaded by plugin html (using the `resources` API)

```auto
const Content = $('<div>')
const Template = Handlebars.compile($('#TPL_SidePanel').html());
const Data = {Networks:[{id: 4, name: "Some Network"}]}
Content.append(Template(Data))

RED.sidebar.addTab({
   ....
   content: Content,
   ...		
});

```

@TotallyInformation  
For the stacks I use the Node RED CSS classes, and for the tree views, use the built in methods.

---

<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:** [16 October 2023 17:11 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/25 "2023-10-16T17:11:56Z")

</div>

> [@marcus-j-davies](#):
>
> tree views, use the built in methods.

Undoubtedly, you have a better memory than me and probably know the core code better as well - do you have a hint? 🙂

> [@marcus-j-davies](#):
>
> HTML Template

That is interesting because I've started using templates in the html file for uibuilder as well. Just in the `uib-element` node and they are all fairly blank right now but will be used dynamically to swap the Element Config tab depending on the selected element type:

 ![image](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/6/1/61a4140af9b64b041881620abe8f683491a97d09.png)

Allowing for different advanced config settings by element type.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [16 October 2023 17:25 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/26 "2023-10-16T17:25:31Z")

</div>

I like using templates - to aid in the detachment between the developer and the designer  
(but in this case - I'm both 😆) - but it helps (a lot) to get focus on the design.

And yes - it nice being able to `empty()` and re-populate based on a template for the selection

For a tree view, here is an example from my code base.

```auto
const TreeData = [];
ZWNodes.forEach((N) => {
    const Label = $('<div>');
    Label.append(`<span class="zwave-js-node-id-list">${N.nodeId}</span> `);
    Label.append(N.nodeName || 'No Name');

    TreeData.push({
        element: Label,
        nodeData: N
    });
});
$('#zwave-js-node-list').treeList('data', TreeData);

```

Note the custom property `nodeData`  
the element with id `zwave-js-node-list` is of course in my template html

```auto
$('#zwave-js-node-list').on('treelistselect', nodeSelected);
const nodeSelected = (event, item) => {
		 //item.nodeData.nodeName etc etc
}

```

[https://nodered.org/docs/api/ui/treeList/](https://nodered.org/docs/api/ui/treeList/)

---

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [16 October 2023 17:57 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/27 "2023-10-16T17:57:16Z")

</div>

One more question, in this setup for a sidebar panel, where can I setup a http admin post point for retrieving data from the server?

I tried adding the server part to the .js file for the config node:

```auto
module.exports = function (RED) {
  function ConfigservercommfromsidebarFunctionality(config) {
    RED.nodes.createNode(this, config)
  }
  RED.nodes.registerType('servercommfromsidebarCfg', ConfigservercommfromsidebarFunctionality);

  console.error( "starting listener") // seen in the server logs

  RED.httpAdmin.post("/servercommfromsidebar",
    RED.auth.needsPermission("servercommfromsidebar.write"),
    (req, res) => {
      console.error("REQUEST RECIEVED")
            res.status(200).send({
              "status": "ok",
            })
    });
}

```

The starting listener stanza is to be found in the log but the httpAdmin endpoint is 404, not found.

So the idea is that when I open the sidebar and hit the button, it sends a request to the server and then something else happens. Unfortunately the server part isn't working yet.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [16 October 2023 18:01 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/28 "2023-10-16T18:01:26Z")

</div>

I have been caught here in the past, I found my error was I was adding a slash at the start in client code

Bad  
`getJSON("/servercommfromsidebar")`

Good  
`getJSON("servercommfromsidebar")`

might be worth checking

---

<div class="post-metadata">

**Author:** ![gregorius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/gregorius/32/73816_2.png) [@gregorius](https://discourse.nodered.org/u/gregorius)\
**Post date:** [16 October 2023 19:51 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/29 "2023-10-16T19:51:12Z")

</div>

yes the slash prevents `httpAdminRoot` configuration from settings.js having an effect on the frontend request

---

<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:** [27 October 2023 16:26 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/30 "2023-10-27T16:26:09Z")

</div>

Note that I have updated my original code above, based on some feedback from @gregorius 👍

The original sidebar was initialized every time the 'Deploy' button was clicked. Because the wrong 'runtime-state' event handler was removed, e.g. the handler of another sidebar.

The code is now refactored to something like this, to make sure our sidebar event handler function is only called once (i.e. when all the nodes have been loaded):

```auto
var initializeSidebar = function( ) { 
   // Remove the event handler, to avoid that the sidebar is initialized at every deploy
   RED.events.off('runtime-state', initializeSidebar); 
    ...
}

// Add your plugin as a new tabsheet in the right sidebar AFTER the flow editor is completely started
RED.events.on('runtime-state', initializeSidebar);

```

---

<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:** [26 December 2023 16:26 UTC](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020/31 "2023-12-26T16:26:27Z")

</div>

Closed on 26 December 2023 16:26 UTC

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

[Previous page](https://discourse.nodered.org/t/tutorial-create-a-sidebar-plugin-and-persist-the-data-in-a-config-node/82020.md?page=1)
