使用bootstrap nav-pill单击“下一步”按钮进行表单验证

I am using nav-pill inside which there is a form and that is split up into each part say as admission details, personal details, family Details with "Next" button on each step and save button at last nav-pill.

$('.btnNext').click(function() {
  $('.nav-pills > .active').next('li').find('a').trigger('click');
});

$('.btnPrevious').click(function() {
  $('.nav-pills > .active').prev('li').find('a').trigger('click');
});

//  Bind the event handler to the "submit" JavaScript event
$('#validateFirst').click(function() {

  // Get the Login Name value and trim it
  var name = $.trim($('#admission_no').val());

  // Check if empty or not
  if (name === '') {
    alert('Admission No. field is empty.');
    return false;
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<ul class="nav nav-pills nav_content">
  <li class="active"><a data-toggle="pill" href="#admission">Admission Details</a></li>
  <li><a data-toggle="pill" href="#personal">Personal Details</a></li>
  <li><a data-toggle="pill" href="#family">Family Details</a></li>
</ul>

<form id="form1" action="<?php echo site_url('student/create') ?>" id="employeeform" name="employeeform" method="post" accept-charset="utf-8" enctype="multipart/form-data">
  <div class="tab-content">
    <div id="admission" class="tab-pane fade in active">
      <div class="row">
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Admission Number *</label>
            <input id="admission_no" name="admission_no" placeholder="" type="text" class="form-control" value="admission_no" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Application Number  *</label>
            <input id="application_no" name="application_no" placeholder="" type="text" class="form-control" value="application_no" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Academic Year  *</label>
            <input id="academic_year" name="academic_year" placeholder="" type="text" class="form-control" value="academic_year" />
          </div>
        </div>
      </div>
      <a class="btn btn-primary btnNext pull-right" id="validateFirst">Next</a>
    </div>
    <div id="personal" class="tab-pane fade">
      <div class="row">
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">First Name *</label>
            <input id="firstname" name="firstname" placeholder="" type="text" class="form-control" value="firstname" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">DOB *</label>
            <input id="dob" name="dob" placeholder="" type="text" class="form-control" value="DOB" readonly="readonly" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputFile">Address  *</label>
            <textarea id="student_address" name="student_address" placeholder="" class="form-control" rows="2"></textarea>
          </div>
        </div>
      </div>
      <a class="btn btn-primary btnPrevious pull-left">Previous</a>
      <a class="btn btn-primary btnNext pull-right">Next</a>
    </div>
    <div id="family" class="tab-pane fade">
      <div class="row">
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Father Name *</label>
            <input id="father_name" name="father_name" placeholder="" type="text" class="form-control" value="father_name" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Father Occupation *</label>
            <input id="father_occupation" name="father_occupation" placeholder="" type="text" class="form-control" value="father_occupation" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Mother Name *</label>
            <input id="mother_name" name="mother_name" placeholder="" type="text" class="form-control" value="mother_name" />
          </div>
        </div>
      </div>
      <a class="btn btn-primary btnPrevious pull-left">Previous</a>
      <button type="submit" class="btn btn-info pull-right">Save</button>
    </div>
  </div>
</form>

I have tried with button click function while clicking "Next" button like:

$('#validateFirst').click(function () {
    // Get the Login Name value and trim it
    var name = $.trim($('#admission_no').val());
    // Check if empty of not
    if (name === '') {
        alert('Text-field is empty.');
        return false;
    }
});

Where button has id "validateFirst",

<a class="btn btn-primary btnNext pull-right" id="validateFirst">Next</a>

Here it shows alert when the admission no input is not filled but moves to the next tab (i.e.) personal details while clicking the next button. The thing i am in the need is while clicking the next button if the fields in the current nav-pill fields are empty (say admission no field is not filled in first nav pill) and clicking the next button, it should display alert and should not move to next nav-pill to rectify the invalid input fields in the current nav-pill.. I had a look around other questions but I couldn't get a clear solution. Kindly help me with a solution to resolve this issue.

</div>

You can do it like this:

$('.pull-right').click(function () {
    var validationMessage = '';

    // Check inputs are filled.
    $.each($(this).closest('.tab-pane').find('input[type="text"]'), function () {
        if ($(this).val() == '') 
            validationMessage += "Please fill " + $(this).closest('.form-group').find('label').html().replace('*', '') + "
";           
    });

    // Validation is false
    if (validationMessage != '')
        alert(validationMessage);
    else
        $('.nav-pills > .active').next('li').find('a').trigger('click');
});

Online demo (jsFiddle)

You are already having an event handler on the '.btn-next' Defining an another event handler on the same element will just execute both of them in the order you have attached the event handler.(You can change the order by manipulating the bubbling phase and capturing phase, but that will work only if you are using the addEventListener.)

Solution 1:

You can set a boolean variable and assign the validation status to that and check the status before firing the click event on the next nav-pill.

In this approach the order in which you are binding the event handlers matter.

Attached the solution as inline code snippet below

Note: this solution is not scalable and maintainable and its too naive.

Solution 2:

Alternate solution is You need to make sure to validate everything in a single function read the status and fire the nav pill event.

https://jsfiddle.net/8b7pq08a/

Note: If you want to add multiple validations like checkEmpty you need to make some modifications for "listOfRequiredFields". Converting it to an object with validations functions as value will help you in identifying the functions that has to be executed on the field. [UPDATE]

Using the code snippet from the question instead of fiddle.

 var validationStatus = true;
 
//  Bind the event handler to the "submit" JavaScript event
$('#validateFirst').click(function() {

  // Get the Login Name value and trim it
  var name = $.trim($('#admission_no').val());

  // Check if empty or not
  if (name === '') {
    alert('Admission No. field is empty.');
     validationStatus = false;
   }
});

$('.btnNext').click(function() {
if(validationStatus)  $('.nav-pills > .active').next('li').find('a').trigger('click');
});

$('.btnPrevious').click(function() {
  if(validationStatus) $('.nav-pills > .active').prev('li').find('a').trigger('click');
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

<ul class="nav nav-pills nav_content">
  <li class="active"><a data-toggle="pill" href="#admission">Admission Details</a></li>
  <li><a data-toggle="pill" href="#personal">Personal Details</a></li>
  <li><a data-toggle="pill" href="#family">Family Details</a></li>
</ul>

<form id="form1" action="<?php echo site_url('student/create') ?>" id="employeeform" name="employeeform" method="post" accept-charset="utf-8" enctype="multipart/form-data">
  <div class="tab-content">
    <div id="admission" class="tab-pane fade in active">
      <div class="row">
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Admission Number *</label>
            <input id="admission_no" name="admission_no" placeholder="" type="text" class="form-control" value="admission_no" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Application Number  *</label>
            <input id="application_no" name="application_no" placeholder="" type="text" class="form-control" value="application_no" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Academic Year  *</label>
            <input id="academic_year" name="academic_year" placeholder="" type="text" class="form-control" value="academic_year" />
          </div>
        </div>
      </div>
      <a class="btn btn-primary btnNext pull-right" id="validateFirst">Next</a>
    </div>
    <div id="personal" class="tab-pane fade">
      <div class="row">
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">First Name *</label>
            <input id="firstname" name="firstname" placeholder="" type="text" class="form-control" value="firstname" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">DOB *</label>
            <input id="dob" name="dob" placeholder="" type="text" class="form-control" value="DOB" readonly="readonly" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputFile">Address  *</label>
            <textarea id="student_address" name="student_address" placeholder="" class="form-control" rows="2"></textarea>
          </div>
        </div>
      </div>
      <a class="btn btn-primary btnPrevious pull-left">Previous</a>
      <a class="btn btn-primary btnNext pull-right">Next</a>
    </div>
    <div id="family" class="tab-pane fade">
      <div class="row">
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Father Name *</label>
            <input id="father_name" name="father_name" placeholder="" type="text" class="form-control" value="father_name" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Father Occupation *</label>
            <input id="father_occupation" name="father_occupation" placeholder="" type="text" class="form-control" value="father_occupation" />
          </div>
        </div>
        <div class="col-md-3">
          <div class="form-group">
            <label for="exampleInputEmail1">Mother Name *</label>
            <input id="mother_name" name="mother_name" placeholder="" type="text" class="form-control" value="mother_name" />
          </div>
        </div>
      </div>
      <a class="btn btn-primary btnPrevious pull-left">Previous</a>
      <button type="submit" class="btn btn-info pull-right">Save</button>
    </div>
  </div>
</form>

</div>

Form validation should involve more than just checking if a field is filled out or not. For this reason you should use Ajax to submit the relevant data to the server, and use server side form validation.

At the top of your page add a hidden div to display validation errors:

<div class="alert alert-danger col-xs-12 hidden" id="error"></div>

Add a shared "validate" class to all buttons that will trigger your form validation. We will have three distinct sets of validation logic. Give the field an id that matches the function name (for example "validate_1", "validate_2", etc).

<a class="btn btn-primary btnNext pull-right validate" id="validate_1">Next</a>
<a class="btn btn-primary btnNext pull-right validate" id="validate_2">Next</a>

Update your jQuery to include the Ajax POST function. This function submits data to the server where you can use Codeigniter's native form validation:

$('.btnPrevious').click(function() {
  $('.nav-pills > .active').prev('li').find('a').trigger('click');
});


$(document).on('click','.validate',function(e){
    e.preventDefault();
    if($('#error').is(":visible")){
        $('#error').empty().addClass('hidden'); //refresh error message if it was triggered previously
    }
    var form = $(this).closest('form');
    $.ajax({        
        url: this.id,
        type: 'POST',
        data: form.serialize(),
        dataType: 'html',
        success: function(data) {
            var result = $.parseJSON(data);
            if(result["error"]===undefined){
                $('.nav-pills > .active').next('li').find('a').trigger('click');
            }else{
                $('#error').append(result["error"]).removeClass('hidden');
            }
        },
        error: function() { }
    });
});

And then in your controller:

function validate_1(){ //function name matches element id
    $this->load->library('form_validation');    
    $this->form_validation->set_rules('admission_no', 'Admission Number', 'required|integer|greater_than[0]');
    $this->form_validation->set_rules('application_no', 'Application Number', 'required|integer|greater_than[0]');
    $this->form_validation->set_rules('academic_year', 'Academic Year', 'required|integer|greater_than[0]');
    if($this->form_validation->run() == TRUE){
         echo json_encode(array('success' => 1));
    }else{
        echo json_encode(array('error' =>  validation_errors()));
    }
}

function validate_2(){
    $this->load->library('form_validation');    
    $this->form_validation->set_rules('firstname', 'First Name', 'required');
    $this->form_validation->set_rules('dob', 'Date of Birth', 'required');
    $this->form_validation->set_rules('student_address', 'Address', 'required');
    if($this->form_validation->run() == TRUE){
        echo json_encode(array('success' => 1));
    }else{
        echo json_encode(array('error' =>  validation_errors()));
    }
}

This will allow you to verify that the data has been submitted and that it is valid. The user will still be able to click on their own to navigate from one nav pill to another, but they will not be able to submit the form without filling out the necessary fields.

enter image description here