NR offers implicit functionality for developers convenience - yet this functionality just covers the basic tasks for creating nodes. You're trying to go the convenience way - but linking two dynamic dropdowns is beyond those basic tasks.
Being explicit solves your issue within one line:
oneditprepare : function() {
console.log("## on edit prepare");
let node = this; // <--- see comment below!
console.log(node.meal_type, node.meal);
$('#node-input-meal_type').on('change', function() {
console.log("## meal type is changed ##");
var sel = document.getElementById("node-input-meal_type");
console.log("## selected meal type: " + sel.value);
var drop = document.getElementById("node-input-meal");
if(sel.value == 'breakfast') {
var opt1 = document.createElement('option');
opt1.value = "sel";
opt1.innerHTML = "Select";
opt1.selected = true;
drop.appendChild(opt1);
[...]
drop.value = node.meal; // <--- be explicit !!
} else if(sel.value == 'lunch') {}
} else if(sel.value == 'dinner') {}
});
Additionally, it's good practice to add - as I did - sth like
Though I'm no longer a professional developer, 40+ years of experience has taught that, for me at least, clean code absolutely does help solve issues - including this one.
I rushed the output as I only had a few minutes. What is missing is to clear the meal input when the meal type changes - that's the last part. No, I see what is happening, because of the order that html is triggered, you lose the existing meal selection each time. So you need to check whether the type as really changed. I'll find some time later to find a fix.
Now I've had the chance to look at the code in more detail, I've spotted a couple of other issues that arise from the way that Node-RED creates the HTML when the panel opens. I've got a fix, but real work gets in the way .
Right, so that WAS actually slightly harder than I'd thought. It needed a bit of rethinking.
The issue, as mentioned, is that because Node-RED rebuilds the panel when you open it, your dynamically created drop-down list has to be recreated each time.
oneditprepare : function() {
const that = this
console.log("## on edit prepare")
// NB: Will fire when panel opens & when user changes
$('#node-input-meal_type').on('change', function() {
const meal = $("#node-input-meal")
// We need the current DOM value of the dropdown
const mealType = $(this).val()
// NB: Current DOM value and Node-RED's stored value may be different
console.log(`š“## meal type changed. type: "${mealType}", meal: "${meal.val()}". Stored values - Type: "${that.meal_type}", Meal: "${that.meal}"`)
// Clear the dynamic dropdown & add a dummy entry
meal.empty()
meal.append('<option value="">Select an option</option>')
// Add the dynamic entries depending on the meal type
switch (mealType) {
case 'breakfast': {
meal.append('<option value="tea">Tea</option>')
meal.append('<option value="milk">Milk</option>')
break
}
case 'lunch': {
meal.append('<option value="ham sandwich">Ham Sandwitch</option>')
meal.append('<option value="cheese sandwich">Cheese Sandwitch</option>')
break
}
case 'tea': {
meal.append('<option value="burger">Burger</option>')
meal.append('<option value="steak">Steak</option>')
break
}
default: {
break
}
}
// Reset the meal (since we rebuilt the menu)
$("#node-input-meal").val(that.meal)
// If meal value is null, that means the meal type
// changed so the previously selected meal is no longer valid
// and we have to change it - to the default
if ($("#node-input-meal").val() === null) $("#node-input-meal").val('')
})
},