Drop down menu items not being selectable in web page using datalist and java

Hi, I'm writing a code with html for a login page in order to get wifi ssid and password from user and connect esp32 to a local modem using a mobile phone as a medium. when i click on the ssid section the drop down menu is populated correctly by the server side and is shown. the problem is that these ssids are not selectable and when i click on them nothing happens. i tried googling and asking AI for help but it didnt work. here is my html code

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Wi-Fi Selection</title>
  <link rel="stylesheet" href="./normalize.min.css">
  <link rel="stylesheet" href="./style.css">
</head>
<body>
<form action="/get" name="Divertpage" class="form-horizontal login-form">
  <div class="form-group relative">
    <div class="form" id="form">
      <div class="field email">
        <div class="icon"></div>
        <fieldset>
          <label>انتخاب شبکه مورد نظر</label>
          <input autocomplete="off" role="combobox" list="ssidList" id="input" name="ssid" placeholder="شبکه مورد نظر را انتخاب کنید">
          <!-- The list attribute should match the id of the datalist -->
          <datalist id="ssidList" role="listbox">
          </datalist>
        </fieldset>

        <div class="field password">
          <div class="icon"></div>
          <input class="input" id="password" type="password" placeholder="رمز عبور"/>
        </div>
        <button class="button" type="submit" onclick="WaitPls()">ذخیره
          <div class="side-top-bottom"></div>
          <div class="side-right-left"></div>
        </button>
        <small>فرم را پر کنید</small>
      </div>
    </div>
  </div>
</form>

<script src='./jquery.min.js'></script>
<script src="./script.js"></script>
<script>
  // Fetch scanned Wi-Fi networks and populate the dropdown
  function fetchWifiNetworks() {
    fetch('/wifi_scan')
      .then(response => response.text())
      .then(data => {
        document.getElementById('ssidList').innerHTML = data;
      });
  }

  // Call fetchWifiNetworks on page load
  window.onload = fetchWifiNetworks;

  function WaitPls() {
    var ssid = document.forms["Divertpage"]["ssid"].value;
    var password = document.forms["Divertpage"]["password"].value;

    if (ssid == "") {
      // alert("نام کاربری را وارد نمایید.");
      return false;
    } else if (password == "") {
      // alert("رمز عبور را وارد نمایید.");
      return false;
    } else {
      // Redirect to waiting page after form submission
      window.location.href = "/Wait";
    }
  }
</script>

<script>
  var input = document.getElementById('input');
  var ssid = document.getElementById('ssidList');

  input.onfocus = function () {
    ssid.style.display = 'block';
    input.style.borderRadius = "5px 5px 0 0";  
  };
  
  input.oninput = function() {
    var text = input.value.toUpperCase();
    for (let option of ssid.options) {
      if(option.value.toUpperCase().indexOf(text) > -1){
        option.style.display = "block";
      } else {
        option.style.display = "none";
      }
    };
  };

  for (let option of ssid.options) {
    option.onclick = function () {
      input.value = option.value;
      ssid.style.display = 'none';
      input.style.borderRadius = "5px";
    }
  };
  
  var currentFocus = -1;

  function addActive(x) {
    if (!x) return false;
    removeActive(x);
    if (currentFocus >= x.length) currentFocus = 0;
    if (currentFocus < 0) currentFocus = (x.length - 1);
    x[currentFocus].classList.add("active");
  }
  
  function removeActive(x) {
    for (var i = 0; i < x.length; i++) {
      x[i].classList.remove("active");
    }
  }
</script>

</body>
</html>

And here is the related task from server side

void wifiScanTask(void *parameter)
{
  while (true)
  {
      Serial.println("scanning networks");
      int n = WiFi.scanNetworks();
      if (n > 0)
      {
        scannedNetworks = "<option value=\"\">انتخاب شبکه مورد نظر</option>";
        for (int i = 0; i < n; ++i)
        {
          scannedNetworks += "<option value=\"" + WiFi.SSID(i) + "\">" + WiFi.SSID(i) + "</option>";
          if (i == (n - 1))
          {
            Serial.println("i is n-1");
            wifi_scan_resume_flag=1;
            first_time_scan=0;
            vTaskSuspend(NULL);
          }
        }
      }
      else
      {
        scannedNetworks = "<option value=\"\">شبکه ای یافت نشد</option>";
      }
    // Wait for 10 seconds before scanning again
    vTaskDelay(20000 / portTICK_PERIOD_MS);
  }
}

What might be the problem here ?

Thanks in advance !

can you double check the HTML you generate, it should look like this for the datalist

<label for="SSID choice">انتخاب شبکه مورد نظر</label>
<input list="ssid-flavors" id="ssid-choice" name="ssid-choice"/>

<datalist id="ssid-flavors">
  <option value="FBI Surveillance Van"></option>
  <option value="Virus Distribution Center"></option>
  <option value="Hide Yo Kids, Hide Yo Wi-Fi"></option>
  <option value="You’ve Been Hacked"></option>
  <option value="Hackers Paradise"></option>
</datalist>

Thanks for the answer but the options are dynamic and should be generated by the java script by getting data from wifi scanner task

I understand that - I’m saying verify that this is actually what’s getting generated

This should not be an "option value" tag. You probably want to display this as a header text above the input box, so it'll need to appear elsewhere in your HTML code.

In your HTML, you'll have to insert some kind of placeholder here that your c++ code will look for and then replace with the list of options.

The way to figure this out is to start simple. Forget about the input list for a minute and just let your HTML show the list of numbers or something. Create a small HTML template that just has a few <html>, <head>, <body> and <ul> tags and a placeholder for where the list items will come. Then make your code put out list items that go 1, 2, 3 etc. You can easily make this list with a for-loop. By doing it this way, you will actually understand what happens in your code so you can then move on to a more complex version that actually populates your list.

1 Like

I checked the generated string its correct and i also used this snippet and it worked for static input and the options are clickable this way but when i generate the options using java and the wifi task the options are not selectable

<datalist id="ssidList" role = "listbox">
<option value = "one">one</options>
<option value = "two">two</options>
<option value = "three">three</options>
<option value = "four">four</options>
<option value = "five">five</options>
</datalist>

I think this might be my problem here but apparently datalist doesn't have placeholder attribute

My problem is solved for now thanks guys
Here is the script i used that worked

// Fetch scanned Wi-Fi networks and populate the dropdown
function fetchWifiNetworks() {
  fetch('/wifi_scan')
    .then(response => response.text())
    .then(data => {
      const ssidList = document.getElementById('ssidList');
      ssidList.innerHTML = data;
      
      // Attach click event listeners to new options
      for (let option of ssidList.options) {
        option.onclick = function () {
          document.getElementById('input').value = option.value;
          ssidList.style.display = 'none';
          document.getElementById('input').style.borderRadius = "5px";
        };
      }
    });
}

// Call fetchWifiNetworks on page load
window.onload = fetchWifiNetworks;

// Show/hide the datalist on focus/input
var input = document.getElementById('input');
var ssid = document.getElementById('ssidList');

input.onfocus = function () {
  ssid.style.display = 'block';
  input.style.borderRadius = "5px 5px 0 0";  
};

input.oninput = function() {
  var text = input.value.toUpperCase();
  for (let option of ssid.options) {
    if(option.value.toUpperCase().indexOf(text) > -1){
      option.style.display = "block";
    } else {
      option.style.display = "none";
    }
  }
};

// This code snippet can be removed as it doesn't apply to datalist options directly
// for (let option of ssid.options) {
//   option.onclick = function () {
//     input.value = option.value;
//     ssid.style.display = 'none';
//     input.style.borderRadius = "5px";
//   }
// }

// Add active class handling (if needed for navigation via keyboard)
var currentFocus = -1;

function addActive(x) {
  if (!x) return false;
  removeActive(x);
  if (currentFocus >= x.length) currentFocus = 0;
  if (currentFocus < 0) currentFocus = (x.length - 1);
  x[currentFocus].classList.add("active");
}

function removeActive(x) {
  for (var i = 0; i < x.length; i++) {
    x[i].classList.remove("active");
  }
}

The other parts of the code are same as before

glad you solved it

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