0

I am still a newbie and I have been working on this code... The idea is to replicate the google sign-up form wherein input types were grouped and are shown only after the previous group of input types was answered.

The way that I want to approach this is to group them into wrapper tags and select them via jquery. Here is the my code:

$(function() {
  var divs = $("#wrapper");

  $("#next").click(function() {
    var div = divs[0];
    div.hide();
  })
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<div class="cover">
  <form method="post" action="">
    <div id="wrapper" class="wrapper">
      <h1>Identity</h1>
      <label>First Name</label><input type="text" name="fname"><br><br>
      <label>Last Name</label><input type="text" name="lname"><br><br><br>
      <label>Civil Status</label>
      <select name="civil_status" id="cv_stat">
        <option value="Single">Single</option>
        <option value="Married">Married</option>
        <option value="Widowed">Widowed</option>
        <option value="Annulled">Anulled</option>
      </select><br><br>
      <label>Email</label><input type="email" name="email"><br><br>
      <div id="next" class="next">
        <div>Next</div>
      </div>
    </div>
    <div id="wrapper" class="wrapper">
      <h1>Identity</h1>
      <label>First Name</label><input type="text" name="fname"><br><br>
      <label>Last Name</label><input type="text" name="lname"><br><br><br>
      <label>Civil Status</label>
      <select name="civil_status" id="cv_stat">
        <option value="Single">Single</option>
        <option value="Married">Married</option>
        <option value="Widowed">Widowed</option>
        <option value="Annulled">Anulled</option>
      </select><br><br>
      <label>Email</label><input type="email" name="email"><br><br>
      <div id="next" class="next">
        <div>Next</div>
      </div>
    </div>
    <div id="wrapper" class="wrapper">
      <h1>hello</h1>
      <label>First Name</label><input type="text" name="fname"><br><br>
      <label>Last Name</label><input type="text" name="lname"><br><br><br>
      <label>Civil Status</label>
      <select name="civil_status" id="cv_stat">
        <option value="Single">Single</option>
        <option value="Married">Married</option>
        <option value="Widowed">Widowed</option>
        <option value="Annulled">Anulled</option>
      </select><br><br>
      <label>Email</label><input type="email" name="email"><br>
    </div>
  </form>
</div>

However I tried targeting the second element with the wrapper tag using the jQuery code shown, and it kept on producing this kind of error:

registration.js:7 Uncaught TypeError: div.css is not a function
at HTMLDivElement.<anonymous> (registration.js:7)
at HTMLDivElement.dispatch (jquery.min.js:2)
at HTMLDivElement.v.handle (jquery.min.js:2)

Any insights or idea on what I have done wrong? I am really stuck here. Thank you

2
  • IDs must be unique on a document, so that's the first problem. To get the "next wrapper" from a button inside a wrapper, consider using $(this).closest(".wrapper").next() to navigate the DOM. Commented Apr 11, 2021 at 10:37
  • Wow, thanks! It actually worked! I have been working for it for a long time thank you! Commented Apr 11, 2021 at 10:42

1 Answer 1

1

The semantically correct approach here would be to use fieldset element as the wrapper elements - a fieldset is used to group like or similar field inputs into a collective group. The legend element is the related element to give a heading or title to the fieldset.

Without trying to resolve everything - and focusing only on the idea of showing the next group of fields based on user interaction - you could apply a "hidden" class with display: none to the fieldsets. and then selectively remove the class (and therefore show the fieldset based on the user interaction (such as clicking the next button.

Obviously more has to be done with this - validation if desired to make sure that all inputs are filled in before moving onto the next section. Hiding the next button from the fieldsets that are already showing (or even toggling the old fieldset out and having a "Back" button to navigate to previously filled in fieldsets.

But what I am trying to get to is that by applying the fieldset correctly - all you need to do is target the fieldset to show / hide the children fields and change it on based on the user interaction.

also - as noted - ids must be unique and I am not a fan of using <br/> elements to cause line breaks and add spacing - that's what display: block and margin CSS style rules are for. But I left it all in there since its what you had.

So to show the outcome - fill in the fields that are showing and then click "Next" and you will see that the next fieldset and associated fields will appear.

const nextButtons = document.querySelectorAll('.next');
  nextButtons.forEach(function(nextButton){
  nextButton.addEventListener('click', showNextFieldset);
})

function showNextFieldset(){
  // show next fieldset by removing the hidden class from the first matching fieldset
   document.querySelector('.question-group.hidden').classList.remove('hidden');
    
     // hide previous "next" button by adding the hidden class to the first matching button
   document.querySelector('button:not(.hidden)').classList.add('hidden');
}
.button-wrapper {
  text-align:right
}

fieldset {
  border: none;
}

legend {
  font-size: 18px;
  font-weight: 600;
}

label{
  display: inline-block;
  width: 100px;
}

input, select{
  display: inline-block;
  width: 200px;
}



.hidden {
 display: none;
}
<div class="cover">
  <fieldset class="question-group">
    <legend>Identity</legend>
    <label>Title</label>
    <select name="civil_status" id="cv_stat">
        <option value=""selected disabled></option>
        <option value="Mr">Mr</option>
        <option value="Mrs">Mrs</option>
        <option value="Ms">Ms</option>
        <option value="Other">Other</option>
    </select><br><br>
    <label>First Name</label>
    <input type="text" name="fname"><br><br>
    <label>Last Name</label>
    <input type="text" name="lname"><br><br>
    <div class="button-wrapper">
        <button type="button" class="next">Next</button>
    </div>
  </fieldset>  
  
  <fieldset class="question-group hidden">
    <legend>Contact</legend>
    <label>Phone number</label>
    <input type="text" name="phNumber"><br><br>
    <label>Mobile Number</label>
    <input type="text" name="mobileNumber"><br><br><br>
    <label>Email</label>
    <input type="email" name="email"><br><br>
    <div class="button-wrapper">
        <button type="button" class="next">Next</button>
    </div>
  </fieldset>  
  
  
    <fieldset class="question-group hidden">
    <legend>Status</legend>
    <label>Civil Status</label>
    <select name="civil_status" id="cv_stat">
        <option value="Single">Single</option>
        <option value="Married">Married</option>
        <option value="Widowed">Widowed</option>
        <option value="Annulled">Anulled</option>
    </select><br><br>
  </fieldset>  
</div>

Sign up to request clarification or add additional context in comments.

3 Comments

I actually kinda like this answer, I am going to try this too. Thank very much'
thanks - just nore that I have just amended it - so reresh the page to get the changes. as I said - this is only to show the effect - it will need to be tightened up a bit :). Happy coding
There is a thing called hidden API element.hidden which translates to and synchronizes with the Boolean HTML attribute hidden. I recommend to use it instead of trying to replicate it using CSS classes like .hidden or .hide.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.