jQuery Validator仅验证最新的DOM元素

时间:2014-03-10 16:54:22

标签: jquery jquery-validate

我正在尝试创建一项调查,员工可以在完成电话后填写该调查,该调查将用于跟踪交互期间销售的产品或服务。表单可以将无限数量的帐户附加到帐户包装器,并且每个帐户可以将无限数量的贷款附加到其贷款包装器。我正在使用JörnZaefferer的验证插件在提交之前验证调查;但是,该插件仅验证最近添加到表单的帐户。

如何让插件验证整个表单?

我学到的东西:我很笨,复选框应该使用REQUIRE而且永远不需要来自群组

以下是我用于表单的代码。

<form id="survey" method="GET" action="/processSurvey">
    <h1>What products/services were completed during the call?</h1>
    <div id="account-wrapper">
    </div><!-- End Account Wrapper -->
    <button type="submit">Submit</button> <button type="button" onclick="addAccount();">Add Account</button>
    <input type="hidden" name="callID" value="0" />
 </form>

我使用下面的把手模板动态地将帐户附加到帐户包装器:

<script id="account-template" type="text/x-handlebars-template">
  <div id="account-{{id}}" class="account">
    <div class="account-title ui-state-active">Account<button type="button">Remove Account</button></div>
    <div class="service-wrapper">
      <div class="service-container">
        <span class="title">Account</span>
        {{#each account}}
          <span class="service-option">
            <input type="checkbox" class="service service-group-{{accountID}}" name="account[{{accountID}}][service][]" value="{{value}}" /> {{html}}
          </span>
        {{/each}}
      </div>
      <div class="service-container">
        <span class="title">Savings</span>
        {{#each savings}}
          <span class="service-option">
            <input type="checkbox" class="service service-group-{{accountID}}" name="account[{{accountID}}][service][]" value="{{value}}" /> {{html}}
          </span>
        {{/each}}
      </div>
      <div class="service-container">
        <span class="title">Checking</span>
        {{#each checking}}
          <span class="service-option">
            <input type="checkbox" class="service service-group-{{accountID}}" name="account[{{accountID}}][service][]" value="{{value}}" /> {{html}}
          </span>
        {{/each}}
      </div>
      <div class="service-container">
        <span class="title">Cards</span>
        {{#each cards}}
          <span class="service-option">
            <input type="checkbox" class="service service-group-{{accountID}}" name="account[{{accountID}}][service][]" value="{{value}}" /> {{html}}
          </span>
        {{/each}}
      </div>
      <div class="service-container">
        <span class="title">Other</span>
        <textarea class="service service-group-{{id}}" name="account[{{id}}][service][]"></textarea>
      </div>
      <div class="error-container"></div>
    </div>
    <div id="loan-wrapper-{{id}}" class="loan-wrapper">
      <div class="loan-title">Loans<button type="button" onclick="addLoan({{id}});">Add Loan</button></div>
      <div class="loan-container"></div>
    </div>
  </div>
</script>

整个JavaScript:

$(document).ready(function(){
    addAccount();
  });

  $(":button").button();
  var loanCounter = 0;
  var accountCounter = 0;

  $.validator.addMethod("require_from_group", function(value, element, options) {
var validator = this;
var selector = options[1];
var validOrNot = $(selector, element.form).filter(function() {
      return validator.elementValue(this);
}).length >= options[0];

if(!$(element).data('being_validated')) {
      var fields = $(selector, element.form);
      fields.data('being_validated', true);
      fields.valid();
      fields.data('being_validated', false);
}
return validOrNot;
  }, $.format("Please select at least {0} product/service above (or fill in other)."));

  $.validator.addMethod("ignorePlaceholder", function(value,element){
      return this.optional(element) || (value !== element.placeholder);
  },"This field is required.");

  $.validator.addClassRules("required", {
    ignorePlaceholder: true,
    required: true
  }); 

  var validator = $("#survey").validate({
    debug: true,
    errorClass: "error",
    validClass: "valid",
    submitHandler: function(form){
      form.submit();
    },
    invalidHandler: function(){
      alert(validator.numberOfInvalids());
    },
    errorPlacement: function(error, element){
      if($(element).hasClass("service")){
        error.appendTo($(element).parents(".service-wrapper").children("div.error-container"));
      }
    },
    rules: {
    }
  });

  function addAccount(){
    var newAccount = {
      id:accountCounter,
      account:[
        {value:"1",html:"New Account",accountID:accountCounter},
        {value:"13",html:"eStatements",accountID:accountCounter}
      ],
      savings:[
        {value:"2",html:"My Choice",accountID:accountCounter},
        {value:"3",html:"Money Market",accountID:accountCounter},
        {value:"4",html:"Individual Reitrement Account",accountID:accountCounter},
        {value:"5",html:"Individual Retirement Account (Certificate of Deposit)",accountID:accountCounter},
        {value:"6",html:"Certificate of Deposit",accountID:accountCounter}
      ],
      checking:[
        {value:"7",html:"Prosper Checking",accountID:accountCounter},
        {value:"8",html:"ePerks Checking",accountID:accountCounter},
        {value:"9",html:"Protect Checking",accountID:accountCounter},
        {value:"10",html:"Basic Checking",accountID:accountCounter}
      ],
      cards:[
        {value:"11",html:"Credit Card",accountID:accountCounter},
        {value:"12",html:"Debit Card",accountID:accountCounter}
      ]
    }

    var template = Handlebars.compile($("#account-template").html());
    var result = template(newAccount);
    $("#account-wrapper").append(result);

    $("#account-wrapper .account:last :button").button();
    $("#account-wrapper .account:last div.account-title :button").click(function(){
      $(this).parents("div.account").remove();
    });

    $("#account-"+accountCounter).placeholder();
    $("html, body").animate({scrollTop: $("#account-"+accountCounter).offset().top},1000);

    $(".service-group-"+accountCounter).each(function() {
      $(this).rules('add', {
        require_from_group: [1, ".service-group-"+accountCounter]
      });
    });

    accountCounter++;
  }

请注意顶部表单无效,因为我没有选中选项。如果我添加相同的帐户模板并选中一个选项,表单将会提交。

jsFiddle Error

jsFiddle&lt; - 链接到问题的工作副本。请注意表单只关心最近添加的帐户是否有效。

1 个答案:

答案 0 :(得分:1)

我想我终于看到这里出了什么问题。

您不应该使用.addClassRules()方法,因为这仅用于创建分配给class的复合规则。

相反,您应该使用the .rules('add') method,这是为了动态声明新元素的规则。

function addAccount(){
    var newAccount = {
      // your code
      ....
    }

    // your code
    .....

    // add the rule to every element in the newly created group

    var group = ".service-group-" + accountCounter;

    $(group).each(function() {
        $(this).rules('add', {
            require_from_group: [1, group],
            messages: {
                require_from_group: "this is a custom message"
            }
        });
    });

    accountCounter++;
}

修改

我相信OP在他实现它的复杂方式中发现了require_from_group方法的另一个错误。

但是,在required群组中使用标准checkbox规则,默认情况下 ,只需要群组中的一个项目。换句话说,只要组中的所有复选框共享相同的name(就像通常那样),您只需要检查一个项目。

这是OP的演示经过修改,删除了require_from_group方法并将其替换为标准required规则。我还修改了他的模板,以便一个帐户部分中的所有checkbox元素将共享相同的name。它似乎现在正在运作:

http://jsfiddle.net/T2pUS/9/