Home > Software engineering >  How to make multiple dependent dropdown inputs more efficient?
How to make multiple dependent dropdown inputs more efficient?

Time:06-08

I managed to make dependent dropdown list using codes from enter image description here

It works and I get the intended responses. But it seems like the trigger function can only be used once. I meant, when I tried to use GetIslands(this.value) for the second line of entries, it didn't work. Here's how it's like when I tried to use GetIslands(this.value) repeatedly: enter image description here

The dropdown list of islands for Person A was changed when I selected a state for Person B.

So I had to repeat the same block of codes multiple times (hence GetIslands2(this.value) for the second entry). There must be a less redundant way to do it. Can anyone help? Thanks in advance!

HTML & JAVASCRIPT

<label>State</label>
      <select id="state1" onchange="GetIslands(this.value)" required></div>
      <option value="" hidden>Select a state</option>
      <? for(var i = 0; i < states.length; i  ) { ?>      
      <option value="<?= states[i] ?>" ><?= states[i] ?></option>
      <? } ?></select>

<label>Island</label>
    <select name="island" id="island1" required>
    <option value=""  hidden>Select a marine park</option>
    </select>

<label>State</label>
  <select id="state2" onchange="GetIslands2(this.value)" required></div>
  <option value="" hidden>Select a state</option>
  <? for(var i = 0; i < states.length; i  ) { ?>      
  <option value="<?= states[i] ?>" ><?= states[i] ?></option>
  <? } ?></select>

<label>Island</label>
    <select name="island2" id="island2" required>
    <option value=""  hidden>Select a marine park</option>
    </select>

<script>
function GetIslands(state)
  {
  google.script.run.withSuccessHandler(function(ar) 
    {
    console.log(ar);
    
    island1.length = 0;
    
    let option = document.createElement("option");
    option.value = "";
    option.text = "Select an island";
    option.hidden = true;
    island1.appendChild(option);
    
    ar.forEach(function(item, index) 
    {    
      let option = document.createElement("option");
      option.value = item;
      option.text = item;
      island1.appendChild(option);    
    });
    
    }).getIslands(state);
  };

function GetIslands2(state)
  {
  google.script.run.withSuccessHandler(function(ar) 
    {
    console.log(ar);
    
    island2.length = 0;
    
    let option = document.createElement("option");
    option.value = "";
    option.text = "Select an island";
    option.hidden = true;
    island2.appendChild(option);
    
    ar.forEach(function(item, index) 
    {    
      let option = document.createElement("option");
      option.value = item;
      option.text = item;
      island2.appendChild(option);    
    });
    
    }).getIslands(state);
  };
</script>

APPS SCRIPT

function getState() { 
  var ss= SpreadsheetApp.getActiveSpreadsheet();
  var siteSheet = ss.getSheetByName("Sites"); 
  var getLastRow = siteSheet.getLastRow();
  var return_array = [];
  for(var i = 2; i <= getLastRow; i  )
  {
      if(return_array.indexOf(siteSheet.getRange(i, 1).getValue()) === -1) {
        return_array.push(siteSheet.getRange(i, 1).getValue());
      }
  }
  return return_array;  
}

function getIslands(state) { 
  var ss= SpreadsheetApp.getActiveSpreadsheet();
  var siteSheet = ss.getSheetByName("Sites"); 
  var getLastRow = siteSheet.getLastRow();
  var return_array = [];
  for(var i = 2; i <= getLastRow; i  )
  {
      if(siteSheet.getRange(i, 1).getValue() === state){
        return_array.push(siteSheet.getRange(i, 2).getValue());
      }
  }
  const unique = (value,index,self) => {return self.indexOf(value) ===index;}
  var Unique_List=return_array.filter(unique); 
  return Unique_List;  
}

CodePudding user response:

I believe your goal is as follows.

  • When state1 is changed, a value is set to island1. And, when state2 is changed, a value is set to island2. In the current script, in order to achieve this, it is required to use 2 functions of GetIslands and GetIslands2.
  • In your goal, you want to achieve this situation using only the function GetIslands.

In this case, how about the following modification?

Modified script:

In this modification, your showing HTML is modified as follows.

<label>State</label>
<select id="state1" onchange="GetIslands(this)" required></div>
<option value="" hidden>Select a state</option>
<? for(var i = 0; i < states.length; i  ) { ?>      
<option value="<?= states[i] ?>" ><?= states[i] ?></option>
<? } ?></select>

<label>Island</label>
<select name="island" id="island1" required>
<option value=""  hidden>Select a marine park</option>
</select>

<label>State</label>
<select id="state2" onchange="GetIslands(this)" required></div>
<option value="" hidden>Select a state</option>
<? for(var i = 0; i < states.length; i  ) { ?>      
<option value="<?= states[i] ?>" ><?= states[i] ?></option>
<? } ?></select>

<label>Island</label>
<select name="island2" id="island2" required>
<option value=""  hidden>Select a marine park</option>
</select>

<script>
function GetIslands(e) {
  const obj = {state1: island1, state2: island2};
  google.script.run.withSuccessHandler(function (ar) {
    console.log(ar);
    obj[e.id].length = 0;
    let option = document.createElement("option");
    option.value = "";
    option.text = "Select an island";
    option.hidden = true;
    obj[e.id].appendChild(option);
    ar.forEach(function (item, index) {
      let option = document.createElement("option");
      option.value = item;
      option.text = item;
      obj[e.id].appendChild(option);
    });
  }).getIslands(e.value);
}
</script>
  • In this modification, an object for converting the edited tag is prepared like const obj = {state1: island1, state2: island2}. And, using this, each tag is managed.
  • Related