You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于jQuery的表单验证优化需求与问题咨询

Hey there! Let's work through each of your validation challenges step by step, updating your existing jQuery validator to cover all your needs.


1. Fix Email Error Message Logic

Your current issue is that the error message disappears as soon as you type anything—we need to only remove it when the input actually matches the email regex. Here's how to adjust the handleError function to validate on keyup before clearing errors:

var handleError = function(element, message, validation) {
  element.addClass('input-error');
  var $err_msg = element.parent('div');
  $err_msg.find('.error').remove();
  var error = $('<div class="error"></div>').text(message);
  error.appendTo($err_msg);
  
  // Validate on keyup/change before removing errors
  element.on('keyup change', function() {
    var isValid = validation.reg.test($(this).val());
    if (isValid) {
      element.removeClass('input-error');
      error.fadeOut(1000, function() { $(this).remove(); });
    }
  });
};

2. Add Validation for Checkbox, Radio, Select, Textarea & File Uploads

We need to extend the validator to handle different field types, since your current code only checks text inputs and textareas. Here's the updated Elements object and modified validate method:

Updated Validation Rules

var Elements = {
  name: {
    reg: /^[a-zA-Z]{2,20}$/,
    error: "Not a valid name (2-20 letters only)."
  },
  email: {
    reg: /^[a-z0-9_+.-]+\@([a-z0-9-]+\.)+[a-z0-9]{2,7}$/i,
    error: "Not a valid e-mail address."
  },
  phone_in: { // Indian 10-digit phone number
    reg: /^[6-9]\d{9}$/,
    error: "Not a valid Indian phone number (10 digits starting with 6-9)."
  },
  message: {
    reg: /^(?!\s*$).+/,
    error: "Message field cannot be empty."
  },
  gender: {
    required: true,
    error: "Please select a gender."
  },
  terms: {
    required: true,
    error: "You must agree to the terms and conditions."
  },
  country: {
    required: true,
    error: "Please select a country."
  },
  attachment: {
    required: true,
    error: "Please upload a file.",
    allowedTypes: ['image/jpeg', 'image/png', 'application/pdf'] // Optional file type check
  }
};

Modified Validate Method

this.validate = function() {
  var errorCount = 0;
  // Clear existing errors first to avoid duplicates
  this.form.find('.input-error').removeClass('input-error');
  this.form.find('.error').remove();

  this.form.find("input, textarea, select").each(function(index, field) {
    var $field = $(field);
    var type = $field.data("validation");
    var validation = Elements[type];

    if (!validation) return;

    // Handle Radio Buttons
    if ($field.is(':radio')) {
      var groupName = $field.attr('name');
      if (!this.form.find('input[name="' + groupName + '"]:checked').length) {
        errorCount++;
        handleError($field, validation.error, validation);
      }
    }
    // Handle Checkboxes
    else if ($field.is(':checkbox')) {
      if (!$field.is(':checked')) {
        errorCount++;
        handleError($field, validation.error, validation);
      }
    }
    // Handle Select Dropdowns
    else if ($field.is('select')) {
      if ($field.val() === '' || $field.val() === null) {
        errorCount++;
        handleError($field, validation.error, validation);
      }
    }
    // Handle File Uploads
    else if ($field.is('input[type="file"]')) {
      var file = $field[0].files[0];
      if (!file) {
        errorCount++;
        handleError($field, validation.error, validation);
      } else if (validation.allowedTypes && !validation.allowedTypes.includes(file.type)) {
        errorCount++;
        handleError($field, "Invalid file type. Allowed types: " + validation.allowedTypes.join(', '), validation);
      }
    }
    // Handle Text/Email/Phone Inputs & Textareas
    else {
      if (!validation.reg.test($field.val())) {
        errorCount++;
        handleError($field, validation.error, validation);
      }
    }
  }.bind(this)); // Bind 'this' to access the form object

  return errorCount === 0;
};

3. Regional Phone Number Support

To support multiple regions, we've added a phone_in rule for India. You can easily add more regional rules (like phone_us for US numbers) to the Elements object, then set the data-validation attribute in your HTML to match the desired rule.

For example, a US phone number rule would look like:

phone_us: {
  reg: /^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/,
  error: "Not a valid US phone number."
}

4. Success Message & Form Reset

Update your form submit handler to show the success message and reset fields only when validation passes:

$(function() {
  $("form#test").on("submit", function(event) {
    event.preventDefault(); // Prevent default form submission
    var validator = new Validator(this);
    
    if (validator.validate()) {
      // Show success message
      $('.success_msg').fadeIn().delay(3000).fadeOut();
      // Reset form fields and clear validation classes
      this.reset(); // Native form reset is cleanest
      $(this).find('input, textarea, select').removeClass('valid input-error');
    }
  });
});

Full Updated Code

HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form action="#" method="post" id="test">
  <fieldset>
    <legend>Contact information</legend>
    <div>
      <label for="firstname">Firstname:</label>
      <input type="text" name="firstname" id="firstname" data-validation="name" />
    </div>
    <div>
      <label for="lastname">Lastname:</label>
      <input type="text" name="lastname" id="lastname" data-validation="name" />
    </div>
    <div>
      <label for="email">Email:</label>
      <input type="email" name="email" id="email" data-validation="email" />
    </div>
    <div>
      <label for="phone">Phone:</label>
      <input type="tel" name="phone" id="phone" data-validation="phone_in" />
    </div>
    <div>
      <label>Gender:</label>
      <input type="radio" name="gender" value="male" data-validation="gender" /> Male
      <input type="radio" name="gender" value="female" data-validation="gender" /> Female
    </div>
    <div>
      <label>Country:</label>
      <select name="country" data-validation="country">
        <option value="">Select a country</option>
        <option value="in">India</option>
        <option value="us">United States</option>
      </select>
    </div>
    <div>
      <label>Terms:</label>
      <input type="checkbox" name="terms" data-validation="terms" /> I agree to the terms
    </div>
    <div>
      <label>Attachment:</label>
      <input type="file" name="attachment" data-validation="attachment" />
    </div>
    <div>
      <label for="message">Message:</label>
      <textarea name="message" id="message" data-validation="message"></textarea>
    </div>
    <p><input type="submit" value="Submit" /></p>
  </fieldset>
</form>
<div class="success_msg">Form submitted successfully!</div>

CSS

body { background: #fff; color: #333; font: 76% Verdana, sans-serif; }
form { margin: 1em 0 0 2em; width: 90%; }
fieldset { margin: 0; border: 1px solid #ccc; padding-bottom: 1em; }
legend { font-weight: bold; text-transform: uppercase; }
label { float: left; width: 8em; padding-right: 2em; font-weight: bold; }
div { margin-bottom: 15px; }
input, select { font: 1em Verdana, sans-serif; }
textarea { width: 300px; height: 100px; border: 1px solid #ccc; font: 1em Verdana, sans-serif; }
form p { margin: 0; padding: 0.4em 0 0 10em; }
form p input { background: #666; color: #fff; font-weight: bold; padding: 5px 10px; cursor: pointer; }
div.error { clear: left; margin-left: 10.3em; color: red; padding-right: 1.3em; line-height: 1.3; }
.input-error { background: #ff9; border: 1px solid red; }
.success_msg { width: 350px; line-height: 40px; border: 1px solid green; border-radius: 5px; background-color: rgba(213, 255, 187, 0.7); display: none; position: absolute; bottom: 5px; left: 50%; transform: translateX(-50%); z-index: 999; text-align: center; }

JavaScript

var Validator = function(formObject) {
  this.form = $(formObject);

  var Elements = {
    name: {
      reg: /^[a-zA-Z]{2,20}$/,
      error: "Not a valid name (2-20 letters only)."
    },
    email: {
      reg: /^[a-z0-9_+.-]+\@([a-z0-9-]+\.)+[a-z0-9]{2,7}$/i,
      error: "Not a valid e-mail address."
    },
    phone_in: {
      reg: /^[6-9]\d{9}$/,
      error: "Not a valid Indian phone number (10 digits starting with 6-9)."
    },
    message: {
      reg: /^(?!\s*$).+/,
      error: "Message field cannot be empty."
    },
    gender: {
      required: true,
      error: "Please select a gender."
    },
    terms: {
      required: true,
      error: "You must agree to the terms and conditions."
    },
    country: {
      required: true,
      error: "Please select a country."
    },
    attachment: {
      required: true,
      error: "Please upload a file.",
      allowedTypes: ['image/jpeg', 'image/png', 'application/pdf']
    }
  };

  var handleError = function(element, message, validation) {
    element.addClass('input-error');
    var $err_msg = element.parent('div');
    $err_msg.find('.error').remove();
    var error = $('<div class="error"></div>').text(message);
    error.appendTo($err_msg);
    
    element.on('keyup change', function() {
      var isValid = false;
      var $el = $(this);

      if ($el.is(':radio')) {
        var groupName = $el.attr('name');
        isValid = $el.closest('form').find('input[name="' + groupName + '"]:checked').length > 0;
      } else if ($el.is(':checkbox')) {
        isValid = $el.is(':checked');
      } else if ($el.is('select')) {
        isValid = $el.val() !== '' && $el.val() !== null;
      } else if (validation.reg) {
        isValid = validation.reg.test($el.val());
      }

      if (isValid) {
        $el.removeClass('input-error');
        error.fadeOut(1000, function() { $(this).remove(); });
      }
    });
  };

  this.validate = function() {
    var errorCount = 0;
    this.form.find('.input-error').removeClass('input-error');
    this.form.find('.error').remove();

    this.form.find("input, textarea, select").each(function(index, field) {
      var $field = $(field);
      var type = $field.data("validation");
      var validation = Elements[type];

      if (!validation) return;

      if ($field.is(':radio')) {
        var groupName = $field.attr('name');
        if (!this.form.find('input[name="' + groupName + '"]:checked').length) {
          errorCount++;
          handleError($field, validation.error, validation);
        }
      } else if ($field.is(':checkbox')) {
        if (!$field.is(':checked')) {
          errorCount++;
          handleError($field, validation.error, validation);
        }
      } else if ($field.is('select')) {
        if ($field.val() === '' || $field.val() === null) {
          errorCount++;
          handleError($field, validation.error, validation);
        }
      } else if ($field.is('input[type="file"]')) {
        var file = $field[0].files[0];
        if (!file) {
          errorCount++;
          handleError($field, validation.error, validation);
        } else if (validation.allowedTypes && !validation.allowedTypes.includes(file.type)) {
          errorCount++;
          handleError($field, "Invalid file type. Allowed types: " + validation.allowedTypes.join(', '), validation);
        }
      } else {
        if (!validation.reg.test($field.val())) {
          errorCount++;
          handleError($field, validation.error, validation);
        }
      }
    }.bind(this));

    return errorCount === 0;
  };
};

$(function() {
  $("form#test").on("submit", function(event) {
    event.preventDefault();
    var validator = new Validator(this);
    
    if (validator.validate()) {
      $('.success_msg').fadeIn().delay(3000).fadeOut();
      this.reset();
      $(this).find('input, textarea, select').removeClass('valid input-error');
    }
  });
});

内容的提问来源于stack exchange,提问作者Mohammed Wahed Khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:49:40