0

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>
Cobus Kruger
  • 7,369
  • 3
  • 56
  • 96
Jt Tan
  • 155
  • 2
  • 12
  • `id` must be **NOT** repeated in the whole document. – Roy Bogado Feb 11 '20 at 07:50
  • User can randomly add in the same Select type, so the code cant be change. For what i know, in javascript need to use foreach. – Jt Tan Feb 11 '20 at 07:52
  • Read [The W3 documentation](https://www.w3.org/TR/html401/struct/global.html#h-7.5.2) [...] `id = name [CS] This attribute assigns a name to an element. This name must be unique in a document.` – Roy Bogado Feb 11 '20 at 07:55
  • You are not checking element for undefined, always check a function returns what you expect it to return. All id's must be unique and cannot be used for more than one element. – SPlatten Feb 11 '20 at 07:57

4 Answers4

1

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"/>
Maniraj Murugan
  • 6,412
  • 10
  • 56
  • 92
1

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.

The KNVB
  • 1,972
  • 1
  • 19
  • 28
0

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

0

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"/>
trincot
  • 211,288
  • 25
  • 175
  • 211