Jt Tan
Jt Tan

Reputation: 175

Array Question related to both HTML and Javascript

I have this simple bit of code. When the user chooses Others, an <input type=text> should appear.

But it only works when there is only one value selected.

Users can randomly add in the same select type, so the code can't be changed. For what I know, in javascript need to use foreach.

So my question is, how to let each of the <input type=text> appear in EACH of the select elements instead of it only appearing in the first one.

function Pack(val){
 var element=document.getElementById('otherpack');  
 if(val=='others')
   element.style.display='block';
 else  
   element.style.display='none';
} 
<select name="Type[]" onchange='Pack(this.value);' required>
<option value="Orange">Orange</option> 
<option value="Apple">Apple</option>    
<option value="others">Others</option>                          
<input type="text" name="othermethod[]" id="otherpack" style="display:none"/>
</select>

<select name="Type[]" onchange='Pack(this.value);' required>
<option value="Orange">Orange</option> 
<option value="Apple">Apple</option>    
<option value="others">Others</option>                          
<input type="text" name="othermethod[]" id="otherpack" style="display:none"/>
</select>

<select name="Type[]" onchange='Pack(this.value);' required>
<option value="Orange">Orange</option> 
<option value="Apple">Apple</option>    
<option value="others">Others</option>                          
<input type="text" name="othermethod[]" id="otherpack" style="display:none"/>
</select>

Upvotes: 0

Views: 93

Answers (4)

Maniraj Murugan
Maniraj Murugan

Reputation: 9084

I would prefer to make change events into javascript side instead of making it in HTML..

As suggested it is not good to use input inside select so make input outside of select box..

const selectBoxes = document.querySelectorAll('select');

function Pack(select) {
  const selectedInput = select.nextElementSibling;
  if(select.value === 'others')
    selectedInput.style.display='block';
  else  
    selectedInput.style.display='none';
}

selectBoxes.forEach(select => {
  select.addEventListener('change', Pack.bind(this, select))
})
<select name="Type[]" required>
<option value="Orange">Orange</option> 
<option value="Apple">Apple</option>    
<option value="others">Others</option>                          
</select>
<input type="text" name="othermethod[]" id="otherpack" style="display:none"/>

<br>
<br>
<select name="Type[]"  required>
<option value="Orange">Orange</option> 
<option value="Apple">Apple</option>    
<option value="others">Others</option>                          
</select>
<input type="text" name="othermethod[]" id="otherpack" style="display:none"/>

<br>
<br>
<select name="Type[]" required>
<option value="Orange">Orange</option> 
<option value="Apple">Apple</option>    
<option value="others">Others</option>                          
</select>
<input type="text" name="othermethod[]" id="otherpack" style="display:none"/>

Upvotes: 1

coding_cate
coding_cate

Reputation: 71

Have you tried giving them unique ids? if you wanna have the same identifier in different elements, maybe use the class attribute instead.

Hope it helps, good luck !

edit: actually, now I see you're calling them with an id that isn't unique. Give each of the text-inputs their own id and it should work

ids are meant to be unique in the code, so whenever you call your function it assumes that there is only one element with that id

Upvotes: 0

trincot
trincot

Reputation: 350147

id attributes should have unique values, so your selector will always select the first match.

Secondly, input elements are not allowed to be children of select elements. select elements can only have optgroup or option elements as children

It is also best practice to attach listeners via JavaScript code instead of onchange attributes. You can listen at the document level ("event delegation") to avoid repeating several listeners (one per select element).

Here is how it could work:

function Pack(e){
    let select = e.target;
    if (select.name !== "Type[]") return;
    let element = select.nextElementSibling; // this finds the INPUT element
    element.style.display = select.value === "others" ? "block" : "none";
} 

document.addEventListener("change", Pack);
<select name="Type[]" required>
  <option value="Orange">Orange</option> 
  <option value="Apple">Apple</option>    
  <option value="others">Others</option>                          
</select>
<input type="text" name="othermethod[]" style="display:none"/>

<br>
<select name="Type[]" required>
  <option value="Orange">Orange</option> 
  <option value="Apple">Apple</option>    
  <option value="others">Others</option>                          
</select>
<input type="text" name="othermethod[]" style="display:none"/>

<br>
<select name="Type[]" required>
  <option value="Orange">Orange</option> 
  <option value="Apple">Apple</option>    
  <option value="others">Others</option>
</select>
<input type="text" name="othermethod[]" style="display:none"/>

Upvotes: 0

The KNVB
The KNVB

Reputation: 3844

Here is my solution:

function Pack(v) {
  var inputBox=v.nextSibling;
 var selectedValue=v.options[v.selectedIndex].value;
 if (selectedValue=="others") {
    inputBox.style.display='block';
 } else {
    inputBox.style.display='none';
 }
}

This should be the most stable solution.

Upvotes: 1

Related Questions