branche
branche

Reputation: 73

Display and hide fields of a form after select

I have a javascript function that display and hide a div after select. The div contains fields of a form. The div test2 has the fields of the div test1 plus other fields. All the fields are required.

I have 2 problems:

1) When I display test2 and I complete the fields, saving the form is impossible because some fields in test2 are found in test1. This means some fields have the same name.

2) All the fields are required, which means even if I complete the fields in test2 I still can't save because the fields in test1 are not completed and hidden. How can I create a code structure to allow this to save?

function visibilite1(_this) {
  var id = _this.value;
  var divs = document.getElementsByTagName('div');

  for(var no=0;no<divs.length;no++) {
    if (divs[ no].className=='divs') { 
      'divs'
      divs[ no].style.display = "none"; 
    }
  }
  document.getElementById(id).style.display = "block"; 
}


<select name="role" id="role"
onchange="visibilite1(this);hide()" >
  <option value='test1'>Year1</option>
  <option value='test2'>Year2</option>
</select>
<div id="test1" class="divs">
  <label>Name </label>
  <input type="text" name= "name" id= "name" required>  </br>
  <label>User name </label>
  <input type="text" name= "username" id= "username"  required></br>
  <label >Password <em>*</em></label>
  <input type="password"   name= "password" id= "password" required></br>
</div>


<div id="test2" class="divs">
  <label>Name </label>
  <input type="text" name= "name" id= "name" required>  
  <label>User name </label>
  <input type="text" name= "username" id= "username"  required>
  <label>Password <em>*</em></label>
  <input type="password"   name= "password" id= "password" required>
  <input type="text" name= "username" id= "username"  required>
  <label>Adress<em>*</em></label>
  <input type="text"   name= "adress" id= "adress" required>
  <label>Client name</label>
   <?php 
   $sql="select ClientName from claims_follow_up.Client where id 
   !='10001' order by ClientName asc "; 
    $req=mysqli_query($dbc,$sql) or die("Erreur d'execution"); 
    ?> 
   <select name="ClientName" id="ClientName"
   onchange="
   var maVal = document.getElementById('ClientName').value;
   if (maVal == 'Create new client')
   {
   window.open('newClientCreate.php', 'blank', 'scrollbars=yes,    
   resizable=no, top=50, left=155, width=1200, height=700');
   };activer()" required disabled="true" onkeypress="activerSubmit()">
    <option value="">select client </option>
    <?php 
    while($d=mysqli_fetch_array($req)) 
    { 
    echo'<option    
   value="'.$d['ClientName'].'">'.$d['ClientName'].'</option>'; 
     } 
   mysqli_free_result($req); 
   ?>
  <option value="Create new client"  style="color:blue;   
   font-weight:bold">create new client</option>
   </select>
</div>

Upvotes: 2

Views: 101

Answers (5)

Elezar
Elezar

Reputation: 1511

Whenever you hide a div, set all of the inputs inside of it as disabled. When an input is disabled, the required attribute is ignored, and disabled inputs don't get submitted with the form, so you won't have the name collisions on the back-end.

var inputs = divs[no].getElementsByTagName('input');
for (var x = 0, len = inputs.length; x < len; x++) {
    inputs[x].disabled = true;
}

Obviously, when you unhide a div, you'll need to go through and re-enable all of the inputs within that div, as well.

Update: Here's an example using your given code, as requested. First, the JS:

function visibilite1(_this) {
  var inputs;
  var divToShow;
  var id = _this.value;
  var divs = document.getElementsByTagName('div');

  for(var no=0;no<divs.length;no++) {
    if (divs[no].className=='divs') { 
      divs[no].style.display = "none";
      inputs = divs[no].getElementByTagName('input');
      for (var x = 0, len = inputs.lenght; x < len; x++) {
        inputs[x].disabled = true;
      }
    }
  }

  divToShow = document.getElementById(id);
  divToShow.style.display = "block"; 
  inputs = divToShow.getElementByTagName('input');
  for (var x = 0, len = inputs.lenght; x < len; x++) {
    inputs[x].disabled = false;
  }
}

And the HTML (reduced a little, but enough to see what it should look like):

<select name="role" id="role" onchange="visibilite1(this);hide()" >
  <option value='test1'>Year1</option>
  <option value='test2'>Year2</option>
</select>
<div id="test1" class="divs">
  <label>Name </label>
  <input type="text" name= "name" required>  </br>
  <label>User name </label>
  <input type="text" name= "username" required></br>
  <label >Password <em>*</em></label>
  <input type="password"   name= "password" required></br>
</div>

<div id="test2" class="divs">
  <label>Name </label>
  <input type="text" name= "name" required>  
  <label>User name </label>
  <input type="text" name= "username" required>
  <label>Password <em>*</em></label>
  <input type="password"   name= "password" required>
  <input type="text" name= "username" required>
  <label>Adress<em>*</em></label>
  <input type="text"   name= "adress" required>
</div>

Upvotes: 1

gaetanoM
gaetanoM

Reputation: 42044

Another approach is to clone elements and on show/hide putting the right one in the form.In the window onload event I set the select to the desired index and I clone and save the elements, removing from the form the elements hidden. on change I remove the visible element and add the selected one.

var divsCloned = [];

function visibilite1(_this) {
  if (divsCloned.length == 0) {
    return;
  }
  var currDiv = document.getElementsByTagName('div')[0];
  _this.parentNode.removeChild(currDiv);
  _this.parentNode.insertBefore(divsCloned[_this.selectedIndex], _this.nextSibling);
}
window.onload = function() {
  var divs = document.getElementsByTagName('div');
  for (var no = 0; no < divs.length; no++) {
    divsCloned.push(divs[no].cloneNode(true));
    if (no != 0 && divs[no].parentNode) {
      divs[no].parentNode.removeChild(divs[no]);
    }
  }
}
<form>
    <select name="role" id="role"
            onchange="visibilite1(this);">
        <option value='test1'>Year1</option>
        <option value='test2'>Year2</option>
    </select>

    <div id="test1" class="divs">
        <label>Name </label>
        <input type="text" name="name" id="name" required>  </br>
        <label>User name </label>
        <input type="text" name="username" id="username" required></br>
        <label>Password <em>*</em></label>
        <input type="password" name="password" id="password" required></br>
    </div>


    <div id="test2" class="divs">
        <label>Name </label>
        <input type="text" name="name" id="name" required>
        <label>User name </label>
        <input type="text" name="username" id="username" required>
        <label>Password <em>*</em></label>
        <input type="password" name="password" id="password" required>
        <input type="text" name="username" id="username" required>
        <label>Adress<em>*</em></label>
        <input type="text" name="adress" id="adress" required>
    </div>
    <input id="submit" type="submit" value="Submit">
</form>

Upvotes: 1

Neil Atkinson
Neil Atkinson

Reputation: 774

As you've discovered, elements in a html page should never have the same id and different input elements in a html form should not have the same name.

Assuming you want to stay within the world of vanilla javascript and don't want to use a javascript framework (e.g. angular, ember) you could accomplish this by setting the inner html of elements. This way the "hidden" html isn't present in the html markup.

Something like...

<script>
  function hide () {
    console.log("whatever")
  }

  function visibilite1(_this) {
    var formgroup1 = '<div id="test1" class="divs"><label>Name </label><input type="text" name= "name" id= "name" required>  </br><label>User name </label><input type="text" name= "username" id= "username"  required></br><label >Password <em>*</em></label><input type="password"   name= "password" id= "password" required></br></div>'

    var formgroup2 = '<div id="test2" class="divs"><label>Name </label><input type="text" name= "name" id= "name" required><label>User name </label><input type="text" name= "username" id= "username"  required><label>Password <em>*</em></label><input type="password"   name= "password" id= "password" required><input type="text" name= "username" id= "username"  required><label>Adress<em>*</em></label><input type="text"   name= "adress" id= "adress" required></div>'

    var formtestElement = document.getElementById('formtest'); 

    if (_this.value == "test1") {
      formtestElement.innerHTML = formgroup1
    } else if (_this.value == "test2") {
      formtestElement.innerHTML = formgroup2
    };
  }
</script>

<select name="role" id="role"
  onchange="visibilite1(this);hide()" >
  <option value='test1'>Year1</option>
  <option value='test2'>Year2</option>
</select>

<div id="formtest">
  <div id="test1" class="divs">
    <label>Name </label>
    <input type="text" name="name" id="name" required>  </br>
    <label>User name </label>
    <input type="text" name="username" id="username" required></br>
    <label>Password <em>*</em></label>
    <input type="password" name="password" id="password" required></br>
  </div>
</div>

Update: Edited to show the test1 form by default.

Upvotes: 2

Tony Duffill
Tony Duffill

Reputation: 287

Immediate reaction is that IDs in the document must be unique! - form element names can be the same, but that implies that they are part of a group (ie: within option buttons collection where there's only one possible selection).

Best to keep them all unique, else you need to refer specifically to formName plus elementName.

Upvotes: 1

Nidhin Prathap
Nidhin Prathap

Reputation: 722

1st thing don't put same id for 2 components, even if its in different divs... 2nd to achieve ur result, when ever u hide the div, disable the input fields corresponding to it and re-enble it when u need

Upvotes: 1

Related Questions