3

我正在尝试使用 jQuery 来构建一个自制的验证器。我想我在 jQuery 中发现了一个限制:将 jQuery 值分配给 json 变量,然后使用 jQuery 向当前页面添加更多适合该变量查询的 DOM 元素时,似乎没有办法访问那些 DOM添加到适合 json 变量查询的页面的元素。

请考虑以下代码:

var add_form = {
    $name_label: $("#add-form Label[for='Name']"),
    $name: $("#add-form #Name"),
    $description_label: $("#add-form Label[for='Description']"),
    $description: $("#add-form #Description"),
    $submit_button: $("#add-form input#Add"),
    $errors: $("#add-form .error"),
    error_marker: "<span class='error'>&nbsp;*</span>"
}
function ValidateForm() {
    var isValid = true;

    add_form.$errors.remove();

    if (add_form.$name.val().length < 1 ) {
        add_form.$name_label.after(add_form.error_marker);
        isValid = false;
    }
    if (add_form.$description.val().length < 1) {
        add_form.$description_label.after(add_form.error_marker);
        isValid = false;
    }

    return isValid
}
$(function(){
    add_form.$submit_button.live("click", function(e){
        e.preventDefault();
        if(ValidateForm())
        {
        //ajax form submission...
        }
    });
})

这里有一个例子:http: //jsfiddle.net/Macxj/3/

首先,我创建了一个 json 变量来表示 html 添加表单。然后,我创建了一个函数来验证表单。最后,我将表单提交按钮的单击事件绑定到验证表单。

请注意,我使用 jQuery after() 方法在表单中的每个无效字段标签之后放置一个包含“*”的跨度。另请注意,在重新验证之前,我从表单中清除了先前提交尝试的星号(这就是失败的原因)。

显然,调用 add_form.$errors.remove(); 不起作用,因为 $errors 变量仅指向在创建时与其查询匹配的 DOM 元素。在那个时间点,所有标签都没有以 error_marker 变量为后缀。

因此,jQuery 变量在尝试删除它们时无法识别其查询的匹配元素,因为在首次分配变量时它们不存在。如果 jQuery 变量有一个eval()方法来重新评估其包含的查询以查看是否有任何新的 DOM 元素匹配它,那就太好了。可惜...

有什么建议么?

提前致谢!

4

3 回答 3

8

jQuery 对象不是“活动的”是正确的——也就是说,jQuery 对象中的元素集不是动态更新的。(这是一件好事。)

如果您真的想更新任意 jQuery 对象,您可以从以下位置获取用于创建对象的选择器.selector

var els = $('#form input');
els.selector // '#form input'

所以你可以els = $(els.selector);重新查询 DOM。

但是请注意,如果您在初始选择器之后修改了集合(函数,如add, filter,children等),或者如果创建 jQuery 对象时没有使用选择器(通过传递 a DOMElement),那么.selector将毫无用处,因为选择器将为空、不正确,甚至可能无效。

更好的办法是重新构造你的代码,这样你就不会持有一个陈旧的 jQuery 对象;其他答案提出了一些很好的建议。

另外,请确保您也在验证输入服务器端!

于 2012-06-04T03:22:16.167 回答
7

对于将要更改的对象,不要将 JSON 对象引用为静态值,而是将其设为函数:

$errors: function() { return $("#add-form .error"); },

因为它是一个函数,它会在你每次调用时重新评估错误字段add_form.$errors()

于 2012-06-04T02:53:49.510 回答
4

您解决问题的方法存在许多结构性问题:

  1. 避免使用全局变量

    您正在验证的页面上可能并不总是只有一个表单。如果有一天你会决定你将有几种形式。您的add_form变量是全局变量,因此会发生冲突。

  2. 不要使用提交按钮单击事件来检测表单提交。

    如果表单是通过类似 js 调用$("form").submit();或通过 enter 键提交的怎么办?

  3. 如果您不确定在配置对象创建时对象是否已经存在,请存储选择器而不是 DOM 对象。

  4. .live已弃用。改为使用.on

3. 将解决您的实际问题,但我强烈建议解决所有 4 个问题。

对于 2,附加验证器的最佳位置不是在提交按钮上,而是在表单的提交事件上。像这样的东西:

$("#add-form").submit(function(event) {
    event.preventDefault();

    if (validateForm(this))
       $.ajax({
           url: $(this).attr("action"),
           data: $(this).serialize(),
           //ETC
       });
});

请注意,现在该表单也更易于访问。您的配置对象不再需要存储对提交按钮的引用。

您的配置对象现在可以简化为如下所示:

{
    name_label: "Label[for='Name']",
    name: "#Name",
    description_label: "Label[for='Description']",
    description: "#Description",
    errors: ".error",
    error_marker: "<span class='error'>&nbsp;*</span>"
}

在 validateForm 中,您可以按如下方式使用这些选择器:

var $name_label = $(configuration.name_label, this); //Finds the label within the current form.

现在,要允许每个表单使用不同的配置参数,请使用以下内容:

function enableValidation(form, configuration) {
  
 $.extend(configuration, {
     //Default configuration parameters here.
 });

  function validateForm(form) {
     //Your original function here with modifications.
  }

  $(form).submit(funciton(e) {
      if (!validateForm(this))
        e.preventDefault();
  });
}

function enableAjax(form) {
   $(form).submit(function(e){
       if (!e.isDefaultPrevented()) {
           e.preventDefault();
           $.ajax(...);
       }
   });
}


$(function() {
   enableValidation("#add-form", {/*specialized config parameters here*/});
   enableAjax("#add-form");
});
于 2012-06-04T03:05:17.823 回答