Custom node: dynamic editor

Hello,

I need some help with my custom nodes again. In my editor I have a dropdown menu with the options "motion" and "machine". When the option "motion" is selected the editor should ask for values of motionType, motionNumber, and motionTarget. When the option "machine" is selected the editor should ask for value of machineTarget. I will show you my html code below because I don't think I can explain what I want clearly.

<script type="text/javascript">
    RED.nodes.registerType('send-mqtt',{
        category: 'motion kit',
        color: '#a6bbcf',
        defaults: {
            name: {value:""},
			target: {value:""},
			machineTarget: {value:""},
			motionType: {value:""},
			motionNumber: {value:0},
			motionTarget: {value:""}
		},
        inputs:0,
        outputs:1,
		outputLabels: ["mqtt message"],
        icon: "file.png",
        label: function() {
			if (this.target == "machine"){
				return this.name||"mqtt Node-RED/"+this.target+"/"+this.machineTarget; 
			}
			else if (this.target == "motion"){
				return this.name||"mqtt Node-RED/"+this.target+"/"+this.motionType+"/"+this.motionNumber+"/"+this.motionTarget;
			}
            else return this.name||"send-mqtt";
        }
    });
</script>

<script type="text/x-red" data-template-name="send-mqtt">
    <div class="form-row">
        <label for="node-input-name"><i class="icon-tag"></i>Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
    </div>
	
	<div class="form-row">
		<label for="node-input-target"><i class="icon-tag"></i>Target</label>
		<select id="node-input-target">
			<option value="machine">machine</option>
			<option value="motion">motion</option>
		</select>
	</div>
	
	<!-- So when machine is selected this should appear in the editor, but I don't know how to do this :( : -->
	<div class="form-row">
		<label for="node-input-machineTarget"><i class="icon-tag"></i>Machine target</label>
		<select id="node-input-machineTarget">
			<option value="clear">clear</option>
		</select>
	</div>
	
	<!-- And when motion is selected this should appear in the editor, but I don't know how to do this :( : -->
	<div class="form-row">
        <label for="node-input-motionType"><i class="icon-tag"></i>Motion type</label>
		<select id="node-input-motionType">
			<option value="absolute">absolute</option>
			<option value="relative">relative</option>
		</select>
    </div>
	
	<div class="form-row">
        <label for="node-input-motionNumber"><i class="icon-tag"></i>Motion number</label>
        <select id="node-input-motionNumber">
			<option value="1">1</option>
			<option value="2">2</option>
			<option value="3">3</option>
			<option value="4">4</option>
			<option value="5">5</option>
			<option value="6">6</option>
			<option value="7">7</option>
			<option value="8">8</option>
			<option value="9">9</option>
			<option value="10">10</option>
		</select>
    </div>
	
	<div class="form-row">
        <label for="node-input-motionTarget"><i class="icon-tag"></i>Motion target</label>
        <select id="node-input-motionTarget">
			<option value="execute">execute</option>
		</select>
    </div>
</script>

<script type="text/x-red" data-help-name="send-mqtt">
    <p>A node that will create the mqtt message to send to TwinCAT.</p>
</script>

You should use onediprepare function for this kind of manipulations.

 oneditprepare: function() {
           
            $("#div-id-of-motion-machine-selector").change(function() {
                if ($(this).val() === "machine") {
                    $("#div-id-to-show").show();
                    $("#div-id-to-hide").hide();
                }
                else {
                   //do opposite hide-show
                }
            });
        }
1 Like

I'm sorry I do not know how to use the id's properly. Where should I define my id's?

<div class="form-row"> becomes then
<div class="form-row" id="this-is-id-of-this-div">

1 Like

I can't get it to work, it still does not hide the node properties in the editor. Can you help me look what I did wrong?

<script type="text/javascript">
    RED.nodes.registerType('send-mqtt',{
        category: 'motion kit',
        color: '#a6bbcf',
        defaults: {
            name: {value:""},
			target: {value:""},
			machineTarget: {value:""},
			motionType: {value:""},
			motionNumber: {value:0},
			motionTarget: {value:""}
		},
        inputs:1,
        outputs:1,
		outputLabels: ["mqtt message"],
        icon: "file.png",
        label: function() {
			if (this.target == "machine"){
				return this.name||"mqtt Node-RED/"+this.target+"/"+this.machineTarget; 
			}
			else if (this.target == "motion"){
				return this.name||"mqtt Node-RED/"+this.target+"/"+this.motionType+"/"+this.motionNumber+"/"+this.motionTarget;
			}
            else return this.name||"send-mqtt";
        },
		oneditprepare: function(){
			$("#target").change(function(){
				if($(this).val() === "machine"){
					$("#machineTarget").show();
					$("#motionType").hide();
					$("#motionNumber").hide();
					$("#motionTarget").hide();
				}
				else if($(this).val() === "motion"){
					$("#motionType").show();
					$("#motionNumber").show();
					$("#motionTarget").show();
					$("#machineTarget").hide();
				}
			});
		}
    });
</script>

<script type="text/x-red" data-template-name="send-mqtt">
    <div class="form-row">
        <label for="node-input-name"><i class="icon-tag"></i>Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
    </div>
	
	<div class="form-row" id="target">
		<label for="node-input-target"><i class="icon-tag"></i>Target</label>
		<select id="node-input-target">
			<option value="machine">machine</option>
			<option value="motion">motion</option>
		</select>
	</div>
	
	<!-- So when machine is selected this should appear in the editor, but I don't know how to do this :( : -->
	<div class="form-row" id="machineTarget">
		<label for="node-input-machineTarget"><i class="icon-tag"></i>Machine target</label>
		<select id="node-input-machineTarget">
			<option value="clear">clear</option>
		</select>
	</div>

	
	<!-- And when motion is selected this should appear in the editor, but I don't know how to do this :( : -->
	<div class="form-row" id="motionType">
        <label for="node-input-motionType"><i class="icon-tag"></i>Motion type</label>
		<select id="node-input-motionType">
			<option value="absolute">absolute</option>
			<option value="relative">relative</option>
		</select>
    </div>
	
	<div class="form-row" id="motionNumber">
        <label for="node-input-motionNumber"><i class="icon-tag"></i>Motion number</label>
        <select id="node-input-motionNumber">
			<option value="1">1</option>
			<option value="2">2</option>
			<option value="3">3</option>
			<option value="4">4</option>
			<option value="5">5</option>
			<option value="6">6</option>
			<option value="7">7</option>
			<option value="8">8</option>
			<option value="9">9</option>
			<option value="10">10</option>
		</select>
    </div>
	
	<div class="form-row" id="motionTarget">
        <label for="node-input-motionTarget"><i class="icon-tag"></i>Motion target</label>
        <select id="node-input-motionTarget">
			<option value="execute">execute</option>
		</select>
    </div>
</script>

<script type="text/x-red" data-help-name="send-mqtt">
    <p>A node that will create the mqtt message to send to TwinCAT.</p>
</script>

That's because of my initial advice was not clear.
$("#div-id-of-motion-machine-selector").change(function() {

Correct will be
$("#id-of-motion-machine-selector").change(function() {

So you need to listen changes from selector, not the div where selector is. Div does not change, selector does.

1 Like

Thank you very much! It took me some time to figure out where to use which selectors, but it is working now. I'm very new to both javascript and html. I do want to share my solution in case it can help other people.

<script type="text/javascript">
    RED.nodes.registerType('send-mqtt',{
        category: 'motion kit',
        color: '#a6bbcf',
        defaults: {
            name: {value:""},
			target: {value:""},
			machineTarget: {value:""},
			motionType: {value:""},
			motionNumber: {value:0},
			motionTarget: {value:""}
		},
        inputs:1,
        outputs:1,
		outputLabels: ["mqtt message"],
        icon: "file.png",
        label: function() {
			if (this.target == "machine"){
				return this.name||"mqtt Node-RED/"+this.target+"/"+this.machineTarget; 
			}
			else if (this.target == "motion"){
				return this.name||"mqtt Node-RED/"+this.target+"/"+this.motionType+"/"+this.motionNumber+"/"+this.motionTarget;
			}
            else return this.name||"send-mqtt";
        },
		oneditprepare: function(){
			$("#node-input-target").change(function(){
				if($(this).val() === "machine"){
					$("#machineTarget").show();
					$("#motionType").hide();
					$("#motionNumber").hide();
					$("#motionTarget").hide();
				}
				else if($(this).val() === "motion"){
					$("#motionType").show();
					$("#motionNumber").show();
					$("#motionTarget").show();
					$("#machineTarget").hide();				}
				else {
					$("#machineTarget").hide();
					$("#motionType").hide();
					$("#motionNumber").hide();
					$("#motionTarget").hide();
				}
			});
		}
    });
</script>

<script type="text/x-red" data-template-name="send-mqtt">
    <div class="form-row">
        <label for="node-input-name"><i class="icon-tag"></i>Name</label>
        <input type="text" id="node-input-name" placeholder="Name">
    </div>
	
	<div class="form-row" id="target">
		<label for="node-input-target"><i class="icon-tag"></i>Target</label>
		<select id="node-input-target">
			<option value="machine">machine</option>
			<option value="motion">motion</option>
		</select>
	</div>
	
	<div class="form-row" id="machineTarget">
		<label for="node-input-machineTarget"><i class="icon-tag"></i>Machine target</label>
		<select id="node-input-machineTarget">
			<option value="clear">clear</option>
		</select>
	</div>
	
	<div class="form-row" id="motionType">
        <label for="node-input-motionType"><i class="icon-tag"></i>Motion type</label>
		<select id="node-input-motionType">
			<option value="absolute">absolute</option>
			<option value="relative">relative</option>
		</select>
    </div>
	
	<div class="form-row" id="motionNumber">
        <label for="node-input-motionNumber"><i class="icon-tag"></i>Motion number</label>
        <select id="node-input-motionNumber">
			<option value="1">1</option>
			<option value="2">2</option>
			<option value="3">3</option>
			<option value="4">4</option>
			<option value="5">5</option>
			<option value="6">6</option>
			<option value="7">7</option>
			<option value="8">8</option>
			<option value="9">9</option>
			<option value="10">10</option>
		</select>
    </div>
	
	<div class="form-row" id="motionTarget">
        <label for="node-input-motionTarget"><i class="icon-tag"></i>Motion target</label>
        <select id="node-input-motionTarget">
			<option value="execute">execute</option>
		</select>
    </div>
</script>

<script type="text/x-red" data-help-name="send-mqtt">
    <p>A node that will create the mqtt message to send to TwinCAT.</p>
</script>
2 Likes