Change a setting in the node, require re-deploy

I cannot seem to get this working. The desire is that when a user clicks a checkbox in the node's settings and then clicks Done, I want the node-red editor to require a re-deployment.

I have tried:
$("#node-input-check").on("change", () => { RED.view.dirty(true); });

But I seem to be lost.

Hi @RickyVaughn2 - Weclome to the forums

You really don't need to do that!

Given this, in your definition

defaults: {
  someCheckBox: {
    value: false,
    required: true
  },
  ....
}

and ~this in your HTML

<div class="form-row">
	    <label for="node-input-someCheckBox"><i class="fa fa-line-chart"></i> Click Me</label>
	    <input type="checkbox" id="node-input-someCheckBox">
	</div>

Node RED will take care of everything - including marking the flow as requiring a publish.

any changes to the values as defined in your definition - will cause a flag to republish

Thank you for such a quick reply!

My defaults are:
...
pooling: { value: false, required: true },

My HTML is:
...

<div class="form-row">
      <label for="node-input-pooling">
        <i class="fa fa-cogs"></i> Connection Pooling
      </label>
      <input type="checkbox" id="node-input-pooling" data-input-type="pooling">
    </div>

There are some other things, like disabling other settings depending on the state of this checkbox. When I check the pooling box, there is no requirement to republish. I have to move the node.

Is the issue right in front of me and I am just not seeing it, or could I be doing something else that is interfering with the republish requirement?

Unless you have a specific reason, I would remove data-input-type="pooling" - it serves no purpose with a checkbox in Node RED (as far as I'm aware) - and may cause issues actually (i'm not entirely sure).

There are some other things, like disabling other settings depending on the state of this checkbox.

You can store other values, but don't necessarily need to expose them to the front end.

defaults

defaults: {
  someCheckBox: {
    value: false,
    required: true
  },
  someAffectedValue: {
    value: "",
    required: false
  },
  ....
}

oneditsave
See definition properties here: HTML File : Node-RED

oneditsave: function() {
    if ($("node-input-someCheckBox").prop("checked")) {
        $("node-input-someAffectedValue").val("someValue")
    }
}

HTML

<input type="hidden" id="node-input-someAffectedValue">
<div class="form-row">
	    <label for="node-input-someCheckBox"><i class="fa fa-line-chart"></i> Click Me</label>
	    <input type="checkbox" id="node-input-someCheckBox">
</div>

Outside of using a HTTP Admin Interface - the only way to commit values - is to change them
if a definition value changes - it will require a publish, if storing values outside of the definition - you need to invest using the HTTP Admin Interface

Here is my html:

<script type="text/javascript">
  RED.nodes.registerType('mysql-r2', {
    category: 'database',
    color: '#F3B567',
    defaults: {
      name: { value: '' },
      host: { value: 'localhost' },
      database: { value: '' },
      username: { value: '' },
      password: { value: '' },
      sql: { value: '' },
      pooling: { value: false },
      waitForConnections: { value: true },
      connectionLimit: { value: 10 },
      queueTimeout: { value: 10000 },
    },
    inputs: 1,
    outputs: 1,
    icon: 'font-awesome/fa-database',
    label: function () {
      return this.name || 'mysql-r2';
    },
    oneditprepare: function () {
      $("#node-input-pooling").on("change", function () {
        const poolingChecked = $(this).prop("checked");
        $("#node-input-waitForConnections, #node-input-connectionLimit, #node-input-queueTimeout").prop("disabled", !poolingChecked);
      }).trigger("change");

      const inputs = [
        "name",
        "host",
        "database",
        "username",
        "password",
        "sql",
        "pooling",
        "waitForConnections",
        "connectionLimit",
        "queueTimeout",
      ];

      inputs.forEach((input) => {
        const inputElement = $(`#node-input-${input}`);
        const inputValue = this[input];

        if (inputElement.is(":checkbox")) {
          inputElement.prop("checked", inputValue);
        } else {
          inputElement.val(inputValue);
        }

        inputElement.on("change", () => {
          this[input] = inputElement.is(":checkbox") ? inputElement.prop("checked") : inputElement.val();
        });
      });
    },
  });
</script>

<script type="text/html" data-template-name="mysql-r2">
  <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-host">
      <i class="fa fa-server"></i> Host
    </label>
    <input type="text" id="node-input-host" placeholder="Host/msg.host">
  </div>
  <div class="form-row">
    <label for="node-input-database">
      <i class="fa fa-database"></i> Database
    </label>
    <input type="text" id="node-input-database" placeholder="Database/msg.database">
  </div>
  <div class="form-row">
    <label for="node-input-username">
      <i class="fa fa-user"></i> Username
    </label>
    <input type="text" id="node-input-username" placeholder="Username/msg.username">
  </div>
  <div class="form-row">
    <label for="node-input-password">
      <i class="fa fa-lock"></i> Password
    </label>
    <input type="password" id="node-input-password" placeholder="Password/msg.password">
  </div>
  <div class="form-row">
    <label for="node-input-sql">
      <i class="fa fa-code"></i> SQL
    </label>
    <textarea id="node-input-sql" rows="4" placeholder="SQL/msg.sql"></textarea>
  </div>
  <hr>
  <div class="form-row">
    <label for="node-input-pooling">
      <i class="fa fa-cogs"></i> Connection Pooling
    </label>
    <input type="checkbox" id="node-input-pooling">
  </div>
  <div class="form-row">
    <label for="node-input-waitForConnections">
      <i class="fa fa-clock-o"></i> Wait for Connections
    </label>
    <input type="checkbox" id="node-input-waitForConnections">
  </div>
  <div class="form-row">
    <label for="node-input-connectionLimit">
      <i class="fa fa-chain"></i> Connection Limit
    </label>
    <input type="number" id="node-input-connectionLimit" min="1" step="1">
  </div>
  <div class="form-row">
    <label for="node-input-queueTimeout">
      <i class="fa fa-hourglass-end"></i> Queue Timeout (ms)
    </label>
    <input type="number" id="node-input-queueTimeout" min="1" step="1">
  </div>
</script>

<script type="text/markdown" data-help-name="mysql-r2">
This Node-RED node allows you to execute MySQL queries against a specified database table.

### Configuration

The `mysql-r2` node can be configured using the following properties.

* Name: A user-friendly name for the node.
* Database: The name of the MySQL database to connect to.
* Table: The name of the table within the database to execute the query against.
* Username: The username to use to authenticate with the MySQL database.
* Password: The password to use to authenticate with the MySQL database.
* SQL: The SQL query to execute against the specified table.
* Connection Pooling: Enable or disable connection pooling.
* Wait for Connections: Determines whether the pool should wait for a connection to be available when there are no more available connections.
* Connection Limit: The maximum number of connections to create at once.
* Queue Timeout: The maximum number of milliseconds to wait before timing out when waiting for a connection to become available.


### Inputs

The `mysql-r2` node accepts a message with the following properties.

: msg.sql (string) : The SQL query to execute against the specified table. If not set, the query defined in the node configuration will be used.

: msg.host (string) : The SQL query to be used. If not set, the SQL query defined in the node configuration will be used.

: msg.database (string) : The name of the MySQL database to connect to. If not set, the database name defined in the node configuration will be used.

: msg.username (string) : The username to use to authenticate with the MySQL database. If not set, the username defined in the node configuration will be used.

: msg.password (string) : The password to use to authenticate with the MySQL database. If not set, the password defined in the node configuration will be used.


### Outputs

The `mysql-r2` node outputs a message with the following properties.

1. Standard output
: msg.payload (string) : The results of the SQL query as an array of objects. Each object in the array represents a row in the query results, with property names corresponding to the column names in the result set.

</script>

Here is my js:

module.exports = function (RED) {
    "use strict";
    const mysql = require('mysql');

    function MySQLR2Node(config) {
        RED.nodes.createNode(this, config);
        var node = this;

        var pool;

        function updateStatus() {
            if (config.pooling && pool) {
                node.status({ fill: "grey", shape: "dot", text: "pooling" });
            } else {
                node.status({ fill: "grey", shape: "dot", text: "disconnected" });
            }
        }

        updateStatus();

        node.on('input', function (msg) {
            var host = msg.host || config.host;
            var database = msg.database || config.database;
            var username = msg.username || config.username;
            var password = msg.password || config.password;
            var sql = msg.sql || config.sql;

            if (config.pooling && msg.hasOwnProperty('host')) {
                pool = mysql.createPool({
                    host: host,
                    user: username,
                    password: password,
                    database: database,
                    waitForConnections: config.waitForConnections,
                    connectionLimit: config.connectionLimit,
                    queueTimeout: config.queueTimeout
                });
            }

            var getConnection = config.pooling ? pool.getConnection.bind(pool) : (callback) => {
                var connection = mysql.createConnection({
                    host: host,
                    user: username,
                    password: password,
                    database: database
                });
                callback(null, connection);
            };

            node.status({ fill: "yellow", shape: "ring", text: "connecting" });

            getConnection(function (err, connection) {
                if (err) {
                    node.error(err, msg);
                    node.status({ fill: "red", shape: "dot", text: "error" });
                    if (!config.pooling) connection.end();
                    return;
                }

                node.status({ fill: "green", shape: "dot", text: "connected" });

                connection.query(sql, function (err, rows) {
                    if (err) {
                        node.error(err, msg);
                        node.status({ fill: "red", shape: "dot", text: "error" });
                    } else {
                        msg.payload = rows;
                        node.send(msg);
                        updateStatus();
                    }
                    if (config.pooling) {
                        connection.release();
                    } else {
                        connection.end();
                    }
                });
            });
        });
    }

    RED.nodes.registerType("mysql-r2", MySQLR2Node);
}

I still cannot get it to trigger a republish. I know it is something I am doing wrong, but I am not sure what it is. If you feel like it, let me know if you see something. I am just going to push this out with the known issue and hopefully someone might help fix it.

It is for this

Thank you :slight_smile:

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