Filter the node in real time

 const filter = () => {
                // Filters options in the select tag.
                let optionEl = options[i];
                let txt = selectTag.options[i].text.toLowerCase();
                if (txt.indexOf(inputEl) > -1) {
                  selectTag.options[i].style.display = "";
                } else {
                  selectTag.options[i].style.display = "none";
                }
              };

This is the code for filtering that happens oneditprepare. Is there any way i could filter it in real time? Like not needing to reopen the node to see results of filter?

Can you explain in more detail?

If the edit dialog is not open there is no list being displayed to be filtered.

If i understand, you mean "while the edit dialog is open" you want this filter to be called - correct?

You need the code to be callable (like in a function) and an event to cause it to be called.

Its down to the structure of your nodes code.

For example, if you want it to be called when a user types, then attach an "on" change event to the text field.


This is my node.If i want to filter it i have to write in the filter input and then reopen the node to see results of that filter.
I want to filter it the second i write something in the filter input.
I tried in vanilla js and its easy there. I dont know how to do it in node-red.

Yeah but how can i attach it on the script type html. I tried doing that and it says filter() is undefined

  elem.on("keyup", filter());

Tried it like this.

Sorry, i dont understand that,

That'll probably be down to scope (where your code is placed)

that should be elem.on("keyup", filter); assuming filter is in scope

The code for filter is in oneditprepare. I tried adding a button that will trigger my function but it still wont trigger until i reopen the node.

You realise that means nothing to us as we can't see your code?

elem.on("keyup", filter());

Assuming filter is a function you have defined and is in scope, then you don't want the () in that statement.

You need to pass filter not call filter()

 fetch(url)
          .then((res) => res.json())
          .then((data) => {
            opt = data;
            opt.forEach((item) => {
              options.push({
                //v: ``,
                v: ``, // Sets the value of the option tag
                t: item.name,
              });
            });

            let selectTag = $("#node-input-options")[0]; // Selects the Select Tag
            let inputEl = $("#node-input-filter").val().toLowerCase();
            let elem = $("#node-input-filter");

            for (let i = 0; i < options.length; i++) {
              let value = options[i].v;
              let text = options[i].t; // Napraviti da svaki option kojeg odaberemo da bude prikazan ili da mu je dodan atribut SELECTED!

              options[i].selected = "selected";
              $("#node-input-options").append(
                $("<option></option>").attr("value", value).text(text) //For every element in the select tag append appropriate value and text (   <option value="#">#</option>    )
              );
              const filter = () => {
                // Filters options in the select tag.
                let optionEl = options[i];
                let txt = selectTag.options[i].text.toLowerCase();
                if (txt.indexOf(inputEl) > -1) {
                  selectTag.options[i].style.display = "";
                } else {
                  selectTag.options[i].style.display = "none";
                }
              };
              const ddselect = () => {
                let displayText = selectTag.options[i].text;
                let areaVal = $("#node-input-txtArea").val();
                areaVal = displayText;
              };

              elem.on("keyup", filter);
              let selectEl = $("#node-input-options");
              selectEl.on("change", ddselect());
            }
          });
      };


This is all my code in oneditprepare

sorry, but the structure of your code is all wrong.

  • filter function should not be inside a loop
  • adding the on change event to the node-input-filter should not be inside the loop

Move the filter function outside of the loop & change it to loop through the options, perform the test, then do a $(el).show() or $(el).hide() based on the test.

const filter = () => {
              // Filters options in the select tag.
              for (let i = 0; i < options.length; i++) {
                let optionEl = options[i];
                let txt = selectTag.options[i].text.toLowerCase();
                if (txt.indexOf(inputEl) > -1) {
                  selectTag.options[i].style.display = "";
                } else {
                  selectTag.options[i].style.display = "none";
                }
              }
            };

            elem.on("keyup", filter);

for now i moved this outside the loop . But it doesnt give back the right filter as before. I type c in filter and on keyup it filters but it filters wrong. I dont rly know jquery so for now i didnt do the show or hide because i dont rly know.Ill fix that but for now i need to fix the filter.
And the filter function triggers only when i press 1st key. After it its dead.

You do not get the latest value of inputEl inside your filter function - so you are always filtering based on whatever value inputEl was originally set to.

Move the line

let inputEl = $("#node-input-filter").val().toLowerCase();

inside your filter function.

And don't forget you can use console.log to add debug to your code to figure out what it is doing. You would have very quickly seen that inputEl was never changing if you had tried that.

You are right. I tried console.log() but with wrong elements. I just dont understand why does it give back the wrong results. For example i type c in filter input and the result is Pump1Running Pump2Running

Nevermind, i made it work.
Thanks very much.

How could i create list item every time i select one of the options?
Tried in JS and it works.

 const ddselect = () => {
        var d = document.getElementById("node-input-options");
        console.log(d);
        let displayText = d.options[d.selectedIndex].text;
        console.log(d.selectedIndex);
        document.getElementById("txtArea").value = displayText;
        let list = document.createElement("ul");
        let listItem = document.createElement("li");
        listItem.innerHTML = displayText;

        list.append(listItem);
        document.body.append(listItem);

As usual i dont know how to do it in node red

Create it where? The code you have is just appending it to the document body. I assume you have an element in your node's html where you want to append it instead?

All the previous code is the same . I just created anoter

<div class="form-row">
    <h3>List of selected data</h3>
    <ul class="list">
// I want to append li here
</ul>
  </div>

This Pump1 is just hardcoded to show u what i want exactly