javascriptjqueryformsvalidationform-submit

When clicking the Submit button on my web form, how come the validation errors for the Input fields display, even when these fields have values?


When testing my web form that was built using HTML, CSS, Bootstrap, PHP and jQuery, the first thing I do is click the Submit button. When I do this, the text-danger errors display below the Input and Text Area fields as expected since the fields are empty. If I add a value in the Input field "Name" and click the Submit button again, the text-danger field continues to display below the Name field. The same goes when I try the same thing for the Email and Security Check fields.

When I add a value in the Message Text Area field, the text-danger error for the message field disappears along with the other errors. The message field needs to have a value in order for the errors for all of the fields to disappear.

How should I set up my jQuery so that once a value is added to a field and I click the Submit button to test, the text-danger error for that specific field no longer displays?

HTML and jQuery Code

  <div class="container">
    <div class="row">
      <form method="post" action="index.php" class="form-horizontal">
         <div class="form-group">
           <label for="name" class="col-sm-2 control-label">Name</label>
           <div class="col-sm-10">
           <input type="text" id="name" name="name" placeholder="Enter your name" class="form-control" value="<?php echo $name;?>">
           <p class="text-danger">You need to enter a name value</p>
           </div>
         </div>
         <div class="form-group">
           <label for="email" class="col-sm-2 control-label">Email</label>
           <div class="col-sm-10">
           <input type="email" id="email" name="email" placeholder="your@email.com" class="form-control" value="<?php echo $email;?>">
           <p class="text-danger">You need to enter a valid email</p>
           </div>
         </div>
         <div class="form-group">
           <label for="message" class="col-sm-2 control-label">Message</label>
           <div class="col-sm-10">
           <textarea id="message" name="message" rows="4" class="form-control"><?php echo $message;?></textarea>
           <p class="text-danger">You need to enter a message</p>
           </div>
         </div>
         <div class="form-group">
           <label for="secCheck" class="col-sm-2 control-label">
           <?php echo $_SESSION["a"] .'+'.$_SESSION["b"];?>
           </label>
           <div class="col-sm-10">
           <input type="text" id="secCheck" name="secCheck" class="form-control">
           <p class="text-danger">Answer the question above</p>
           </div>
         </div>
         <div class="form-group">
          <div class="col-sm-10 col-sm-offset-2"> 
             <input type="submit" value="Send" class="btn btn-primary btn-large btn-block" id="submit" name="submit">
          </div>
         </div>
         <div class="form-group">
          <div class="col-sm-10 col-sm-offset-2"> 
             <?php echo $result; ?>
          </div>
         </div
      </form>   
    </div>
  </div>

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script>

 $('form').on('submit',function(){
     $(".text-danger").hide();
     var holderValue = false;
     $(this).find('input[type!="hidden"]').each(function(){

        if(!$(this).val()){holderValue=true; $(this).parent().find(".text-danger").show();}
     })
     if(!$("#message").val()){holderValue=true; $(this).parent().find(".text-danger").show();};

     if(holderValue){return false;}
     // event.preventDefault();
     // console.log('form submitted');   
     })


$("input").on("change paste keyup", function() {
  if($(this).val()){
 $(this).parent().find(".text-danger").hide();
} 
});

$("textarea").on("change paste keyup", function() {
  if($(this).val()){
 $(this).parent().find(".text-danger").hide();
} 
});


</script>

Solution

  • Bootstrap Custom Form

    There are a couple of key Bootstrap attributes and classes needed for custom validation:

    HTML

    • <form ... novalidate>

    • All <input ... required>

    • Remove all <p class='danger-text'>...

    • Replace the previous with <aside class='invalid-feedback'>

    Also the tags have been changed from <div> to a more semantic tag, but it isn't required. The layout has been changed as well -- originally the layout had only one .row which now has several .form-rows (not sure if that was intentional or not, but it looks better when using .form-control).


    jQuery

    • On each .form-control ...
      $('.form-control').each(function() {...

    • ...if the current .form-control is invalid...
      if ($(this).is(':invalid')) {...

    • ...stop the from submitting and show the invalid message...
      e.preventDefault();
      $(this).next('.invalid-feedback').show();...

    • ...otherwise hide the invalid message if need be.
      } else {
      $(this).next('.invalid-feedback').hide();
      }


    Demo

    $('.invalid-feedback').hide();
    $('#main').on('submit', function(e) {
      $('.form-control').each(function() {
        if ($(this).is(':invalid')) {
          e.preventDefault();
          $(this).next('.invalid-feedback').show();
        } else {
          $(this).next('.invalid-feedback').hide();
        }
      });
    });
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/css/bootstrap.min.css" rel="stylesheet">
    
    <main class="container">
      <form id='main' class="form-horizontal" method="post" action="index.php" novalidate>
    
        <section class="form-row">
          <fieldset class="form-group col-sm-10">
            <label for="name" class="control-label">
              Name
            </label>
            <input id="name" name="name" class="form-control" type="text" placeholder="Enter your name" required>
            <aside class="invalid-feedback">
              You need to enter your name.
            </aside>
          </fieldset>
        </section>
    
        <section class="form-row">
          <fieldset class="form-group col-sm-10">
            <label for="email" class="control-label">
              Email
            </label>
            <input id="email" name="email" class="form-control" type="email" placeholder="your@email.com" required>
            <aside class="invalid-feedback">
              You need to enter your email.
            </aside>
          </fieldset>
        </section>
    
        <section class="form-row">
          <fieldset class="form-group col-sm-10">
            <label for="message" class="control-label">
              Message
            </label>
            <textarea id="message" name="message" class="form-control" rows="4" required></textarea>
            <aside class="invalid-feedback">
              You need to enter a message.
            </aside>
          </fieldset>
        </section>
    
        <section class="form-row">
          <fieldset class="form-group col-sm-10">
            <label for="secCheck" class="control-label">
            </label>
            <input id="secCheck" name="secCheck" class="form-control" type="text" required>
            <aside class="invalid-feedback">
              Answer the security question above.
            </aside>
          </fieldset>
        </section>
    
        <section class="form-row">
          <fieldset class="form-group col-sm-10 col-sm-offset-2">
            <input id="submit" name="submit" class="btn btn-primary btn-large btn-block" type="submit" value="Send">
          </fieldset>
        </section>
    
        <section class="form-row">
          <fieldset class="form-group col-sm-10 col-sm-offset-2">
            <output id='result'></output>
          </fieldset>
        </section>
    
      </form>
    </main>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.2.1/js/bootstrap.min.js"></script>