# Node library conflict variables on html file

**URL:** <https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964>\
**Category:** Developing Nodes\
**Tags:** function-node\
**Created:** [7 November 2024 11:26 UTC](https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964 "2024-11-07T11:26:31Z")\
**Posts on this page:** 6\
**Page:** 1

<div class="post-metadata">

**Author:** ![APXc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/apxc/32/96199_2.png) [@APXc](https://discourse.nodered.org/u/APXc)\
**Post date:** [7 November 2024 11:26 UTC](https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964/1 "2024-11-07T11:26:31Z")

</div>

Hi!  
I reelected the following problem in Node-Red 3.0.2 Node v18,

I developed three similar libraries (circumstances made it necessary for them to be three libraries)

we detected in these libraries upon installation of at least two of them in a Node-Red impanto that some nodes were adding to overwrite themselves,

I verified:

- the registration are different

- the assignment in the “packege.json” are different

- the file names are different

after a few hours of debugging I found the cause of the problem it seems that the nodes in their html file encoded in the script part of the variables with the same name,

![immagine](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/7/3/7322a04919360c8e30c905d1694d0f1ddc03440e.png)

once replaced in all of them there was no more conflict/overwriting in installation,

i think it is deeply related to the operation of JQuery in loading the node html

since it is very likely to happen in the future.

is it possible to foresee a bug fix at core level?

---

<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:** [7 November 2024 11:29 UTC](https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964/2 "2024-11-07T11:29:08Z")

</div>

Hi @APXc

Can you share some more details? Is the source code available anywhere for us to have a look? If not, can you try recreating it with a simple example?

> [@APXc](#):
>
> is it possible to foresee a bug fix at core level?

At this point, we don't have enough details to understand the issue.

Nick

---

<div class="post-metadata">

**Author:** ![APXc](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/apxc/32/96199_2.png) [@APXc](https://discourse.nodered.org/u/APXc)\
**Post date:** [7 November 2024 11:42 UTC](https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964/3 "2024-11-07T11:42:37Z")

</div>

Hi @knolleary,

this is a original code on html file before fix

the name variables it's:

- servicesName
- servicesData

library 1

```html
<script type="text/javascript">
  let servicesName = [];
  let servicesData = {};
    $.getJSON('services', (data, status) => {
      for(service in data) {
        servicesData = data;
        servicesName.push(service);
      }
    });
  RED.nodes.registerType('serviceSap',{
    category: 'Sap',
    color: '#FFC300',
    defaults: {
      name: {value: ''},
      serviceName: {value: ''},
      service: {value: ''},
      // entity: {value: ''},
      // udo: {value: ''},
      // udt: {value: ''},
      // entityId: {value: ''},
      // docEntry: {value: ''},
      // code: {value: ''},
      headers: {value: ''},
      bodyPost: {value: ''}
    },
    inputs:1,
    outputs:1,
    icon: 'font-awesome/fa-gears',
    label: function() {
      return this.name||"Sap service";
    },
    oneditprepare: function() {
      // $("#node-input-entityId").typedInput({
      // type:"msg",
      // types:["msg"],
      // typeField: "#node-input-entityId-type",
      // value: 'entityId'
      // });

      // $("#node-input-docEntry").typedInput({
      // type:"msg",
      // types:["msg"],
      // typeField: "#node-input-docEntry-type",
      // value: 'docEntry'
      // });

      // $("#node-input-code").typedInput({
      // type:"msg",
      // types:["msg"],
      // typeField: "#node-input-code-type",
      // value: 'code'
      // });

      $("#node-input-headers").typedInput({
        type:"msg",
        types:["msg"],
        typeField: "#node-input-headers-type",
        value: 'headers'
      });

      $("#node-input-bodyPost").typedInput({
        type:"msg",
        types:["msg"],
        typeField: "#node-input-bodyPost-type",
        value: 'bodyPost'
      });

      // jQuery("#node-input-entity").change(function() {
      // jQuery('#container-udo').hide();
      // jQuery('#container-docEntry').hide();
      // jQuery('#container-udt').hide();
      // jQuery('#container-code').hide();
      // jQuery('#container-entityId').hide();

      // if (jQuery(this).val() === 'UDO'){ 
      // jQuery('#container-udo').show();
      // jQuery('#container-docEntry').show();
      // } 
      // if (jQuery(this).val() === 'UDT'){ 
      // jQuery('#container-udt').show();
      // jQuery('#container-code').show();
      // } 
      // if(jQuery(this).val() !== 'UDO' && jQuery(this).val() !== 'UDT') {
      // jQuery('#container-entityId').show();
      // }
      // });

      servicesName.forEach((service) => {
        $('#node-input-serviceName')
          .append($("<option></option>")
                      .attr("value", service)
                      .text(service)); 
      });

      // set the previous value
      if(this.serviceName) {
        $('#node-input-serviceName').val(this.serviceName);
      }
      

      $("#node-input-serviceName").change((event) => {
        const service = $("#node-input-serviceName").val();

        $('#node-input-service').empty();

        if(servicesData[service]) {
          servicesData[service].forEach((endpoint) => {
          $('#node-input-service')
            .append($("<option></option>")
                        .attr("value", endpoint)
                        .text(endpoint)); 
          });
          // trick check if change with click or not
          if(!event.originalEvent){
            $('#node-input-service').val(this.service);
          }
        }
      });

    }
  });
</script>
  
<script type="text/html" data-template-name="serviceSap">
  <div class="form-row">
    <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>

 <div class="form-row">
    <label for="node-input-type"><i class="fa fa-gears"></i> Service</label>
    <select name="node-input-serviceName" id="node-input-serviceName">
      <option></option>
    </select>
  </div>

  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-gears"></i> Endpoint</label>
    <select name="node-input-service" id="node-input-service">
    </select>
  </div>

  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-cog"></i> Headers</label>
    <input type="text" id="node-input-headers">
    <input type="hidden" id="node-input-headers-type">
  </div>
  
  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-cog"></i> BodyPost</label>
    <input type="text" id="node-input-bodyPost">
    <input type="hidden" id="node-input-bodyPost-type">
  </div>
</script>
  
<!-- Documentation -->
<script type="text/html" data-help-name="serviceSap">
  <p>Post action</p>
  
  <h3>Inputs</h3>
      <dl class="message-properties">
          <dt>Name
            <span class="property-type">string</span>
          </dt>
          <dd> the node's name </dd>
          <dt>Entity
            <span class="property-type">string</span>
          </dt>
          <dd> the entity name of SAP </dd>
          <dt>entityId
            <span class="property-type">number | string</span>
          </dt>
          <dd> the id of the entity of SAP </dd>
          <dt>bodyPost
            <span class="property-type">object</span>
          </dt>
          <dd> data to update to the entity </dd>
      </dl>
  
   <h3>Outputs</h3>
       <ol class="node-ports">
           <li>Standard output
               <dl class="message-properties">
                   <dt>payload <span class="property-type">string</span></dt>
                   <dd>the standard output of the command.</dd>
               </dl>
           </li>
       </ol>
  
  <h3>Details</h3>
      <p>this node is used to update the entity of SAP.
        See the examples to understand how to use it.
      </p>
      <!-- <p><code>msg.payload</code> is used as the payload of the published message.
      If it contains an Object it will be converted to a JSON string before being sent.
      If it contains a binary Buffer the message will be published as-is.</p>
      <p>The topic used can be configured in the node or, if left blank, can be set
      by <code>msg.topic</code>.</p>
      <p>Likewise the QoS and retain values can be configured in the node or, if left
      blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.</p> -->
</script>

```

library 2

```html
<script type="text/javascript">
  let servicesName = [];
  let servicesData = {};
    $.getJSON('services', (data, status) => {
      for(service in data) {
        servicesData = data;
        servicesName.push(service);
      }
    });
  RED.nodes.registerType('serviceLayerOneSL',{
    category: 'LayerOne SL',
    color: '#139ce9',
    defaults: {
      name: {value: ''},
      serviceName: {value: ''},
      service: {value: ''},
      // entity: {value: ''},
      // udo: {value: ''},
      // udt: {value: ''},
      // entityId: {value: ''},
      // docEntry: {value: ''},
      // code: {value: ''},
      headers: {value: ''},
      bodyPost: {value: ''}
    },
    inputs:1,
    outputs:1,
    icon: 'font-awesome/fa-gears',
    label: function() {
      return this.name||"Sap service";
    },
    oneditprepare: function() {
      // $("#node-input-entityId").typedInput({
      // type:"msg",
      // types:["msg"],
      // typeField: "#node-input-entityId-type",
      // value: 'entityId'
      // });

      // $("#node-input-docEntry").typedInput({
      // type:"msg",
      // types:["msg"],
      // typeField: "#node-input-docEntry-type",
      // value: 'docEntry'
      // });

      // $("#node-input-code").typedInput({
      // type:"msg",
      // types:["msg"],
      // typeField: "#node-input-code-type",
      // value: 'code'
      // });

      $("#node-input-headers").typedInput({
        type:"msg",
        types:["msg"],
        typeField: "#node-input-headers-type",
        value: 'headers'
      });

      $("#node-input-bodyPost").typedInput({
        type:"msg",
        types:["msg"],
        typeField: "#node-input-bodyPost-type",
        value: 'bodyPost'
      });

      // jQuery("#node-input-entity").change(function() {
      // jQuery('#container-udo').hide();
      // jQuery('#container-docEntry').hide();
      // jQuery('#container-udt').hide();
      // jQuery('#container-code').hide();
      // jQuery('#container-entityId').hide();

      // if (jQuery(this).val() === 'UDO'){ 
      // jQuery('#container-udo').show();
      // jQuery('#container-docEntry').show();
      // } 
      // if (jQuery(this).val() === 'UDT'){ 
      // jQuery('#container-udt').show();
      // jQuery('#container-code').show();
      // } 
      // if(jQuery(this).val() !== 'UDO' && jQuery(this).val() !== 'UDT') {
      // jQuery('#container-entityId').show();
      // }
      // });

      servicesName.forEach((service) => {
        $('#node-input-serviceName')
          .append($("<option></option>")
                      .attr("value", service)
                      .text(service)); 
      });

      // set the previous value
      if(this.serviceName) {
        $('#node-input-serviceName').val(this.serviceName);
      }
      

      $("#node-input-serviceName").change((event) => {
        const service = $("#node-input-serviceName").val();

        $('#node-input-service').empty();

        if(servicesData[service]) {
          servicesData[service].forEach((endpoint) => {
          $('#node-input-service')
            .append($("<option></option>")
                        .attr("value", endpoint)
                        .text(endpoint)); 
          });
          // trick check if change with click or not
          if(!event.originalEvent){
            $('#node-input-service').val(this.service);
          }
        }
      });

    }
  });
</script>
  
<script type="text/html" data-template-name="serviceLayerOneSL">
  <div class="form-row">
    <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>

 <div class="form-row">
    <label for="node-input-type"><i class="fa fa-gears"></i> Service</label>
    <select name="node-input-serviceName" id="node-input-serviceName">
      <option></option>
    </select>
  </div>

  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-gears"></i> Endpoint</label>
    <select name="node-input-service" id="node-input-service">
    </select>
  </div>

  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-cog"></i> Headers</label>
    <input type="text" id="node-input-headers">
    <input type="hidden" id="node-input-headers-type">
  </div>
  
  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-cog"></i> BodyPost</label>
    <input type="text" id="node-input-bodyPost">
    <input type="hidden" id="node-input-bodyPost-type">
  </div>
</script>
  
<!-- Documentation -->
<script type="text/html" data-help-name="serviceLayerOneSL">
  <p>Post action</p>
  
  <h3>Inputs</h3>
      <dl class="message-properties">
          <dt>Name
            <span class="property-type">string</span>
          </dt>
          <dd> the node's name </dd>
          <dt>Entity
            <span class="property-type">string</span>
          </dt>
          <dd> the entity name of SAP </dd>
          <dt>entityId
            <span class="property-type">number | string</span>
          </dt>
          <dd> the id of the entity of SAP </dd>
          <dt>bodyPost
            <span class="property-type">object</span>
          </dt>
          <dd> data to update to the entity </dd>
      </dl>
  
   <h3>Outputs</h3>
       <ol class="node-ports">
           <li>Standard output
               <dl class="message-properties">
                   <dt>payload <span class="property-type">string</span></dt>
                   <dd>the standard output of the command.</dd>
               </dl>
           </li>
       </ol>
  
  <h3>Details</h3>
      <p>this node is used to update the entity of SAP.
        See the examples to understand how to use it.
      </p>
      <!-- <p><code>msg.payload</code> is used as the payload of the published message.
      If it contains an Object it will be converted to a JSON string before being sent.
      If it contains a binary Buffer the message will be published as-is.</p>
      <p>The topic used can be configured in the node or, if left blank, can be set
      by <code>msg.topic</code>.</p>
      <p>Likewise the QoS and retain values can be configured in the node or, if left
      blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.</p> -->
</script>

```

library 3

```html
<script type="text/javascript">
  let servicesName = [];
  let servicesData = {};
    $.getJSON('services', (data, status) => {
      for(service in data) {
        servicesData = data;
        servicesName.push(service);
      }
    });
  RED.nodes.registerType('you-layerone2-sl-service',{
    category: 'LayerOne2SL',
    color:"#139ce9",
    defaults: {
      name: {value: ''},
      serviceName: {value: ''},
      service: {value: ''},
      headers: {value: ''},
      bodyPost: {value: ''}
    },
    inputs:1,
    outputs:1,
    icon: 'font-awesome/fa-gears',
    paletteLabel: "Service",
    label: function() {
      return this.name||"Sap service";
    },
    oneditprepare: function() {
      $("#node-input-headers").typedInput({
        type:"msg",
        types:["msg"],
        typeField: "#node-input-headers-type",
        value: 'headers'
      });

      $("#node-input-bodyPost").typedInput({
        type:"msg",
        types:["msg"],
        typeField: "#node-input-bodyPost-type",
        value: 'bodyPost'
      });
      servicesName.forEach((service) => {
        $('#node-input-serviceName')
          .append($("<option></option>")
                      .attr("value", service)
                      .text(service)); 
      });

      // set the previous value
      if(this.serviceName) {
        $('#node-input-serviceName').val(this.serviceName);
      }
      

      $("#node-input-serviceName").change((event) => {
        const service = $("#node-input-serviceName").val();

        $('#node-input-service').empty();

        if(servicesData[service]) {
          servicesData[service].forEach((endpoint) => {
          $('#node-input-service')
            .append($("<option></option>")
                        .attr("value", endpoint)
                        .text(endpoint)); 
          });
          // trick check if change with click or not
          if(!event.originalEvent){
            $('#node-input-service').val(this.service);
          }
        }
      });

    }
  });
</script>
  
<script type="text/html" data-template-name="you-layerone2-sl-service">
  <div class="form-row">
    <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
    <input type="text" id="node-input-name" placeholder="Name">
  </div>

 <div class="form-row">
    <label for="node-input-type"><i class="fa fa-gears"></i> Service</label>
    <select name="node-input-serviceName" id="node-input-serviceName">
      <option></option>
    </select>
  </div>

  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-gears"></i> Endpoint</label>
    <select name="node-input-service" id="node-input-service">
    </select>
  </div>

  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-cog"></i> Headers</label>
    <input type="text" id="node-input-headers">
    <input type="hidden" id="node-input-headers-type">
  </div>
  
  <div class="form-row">
    <label for="node-input-type"><i class="fa fa-cog"></i> BodyPost</label>
    <input type="text" id="node-input-bodyPost">
    <input type="hidden" id="node-input-bodyPost-type">
  </div>
</script>
  
<!-- Documentation -->
<script type="text/html" data-help-name="you-layerone2-sl-service">
  <p>Post action</p>
  
  <h3>Inputs</h3>
      <dl class="message-properties">
          <dt>Name
            <span class="property-type">string</span>
          </dt>
          <dd> the node's name </dd>
          <dt>Entity
            <span class="property-type">string</span>
          </dt>
          <dd> the entity name of SAP </dd>
          <dt>entityId
            <span class="property-type">number | string</span>
          </dt>
          <dd> the id of the entity of SAP </dd>
          <dt>bodyPost
            <span class="property-type">object</span>
          </dt>
          <dd> data to update to the entity </dd>
      </dl>
  
   <h3>Outputs</h3>
       <ol class="node-ports">
           <li>Standard output
               <dl class="message-properties">
                   <dt>payload <span class="property-type">string</span></dt>
                   <dd>the standard output of the command.</dd>
               </dl>
           </li>
       </ol>
  
  <h3>Details</h3>
      <p>this node is used to update the entity of SAP.
        See the examples to understand how to use it.
      </p>
      <!-- <p><code>msg.payload</code> is used as the payload of the published message.
      If it contains an Object it will be converted to a JSON string before being sent.
      If it contains a binary Buffer the message will be published as-is.</p>
      <p>The topic used can be configured in the node or, if left blank, can be set
      by <code>msg.topic</code>.</p>
      <p>Likewise the QoS and retain values can be configured in the node or, if left
      blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.</p> -->
</script>

```

---

<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:** [7 November 2024 11:45 UTC](https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964/4 "2024-11-07T11:45:49Z")

</div>

All three of those are adding `servicesName` and `servicesData` to the global scope - so they will overwrite each other.

One solution is to wrap your code in a function:

```auto
;(function () {
   let servicesName = [];
   let servicesData = {};
   $.getJSON('services', (data, status) => {
     for(service in data) {
       servicesData = data;
       servicesName.push(service);
     }
   });
   ...
})()

```

This will keep those variables scoped to your node.

---

<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:** [7 November 2024 12:14 UTC](https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964/5 "2024-11-07T12:14:59Z")

</div>

Yes, this is something I discovered early on and is easily overlooked by new entrants to node development.

Code isolation is quite a tricky concept in relation to Node-RED due to it loading so many different modules.

---

<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:** [21 November 2024 12:15 UTC](https://discourse.nodered.org/t/node-library-conflict-variables-on-html-file/92964/6 "2024-11-21T12:15:22Z")

</div>

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