获取指定的jQuery变量以“重新查询”

时间:2012-06-04 01:58:34

标签: javascript jquery

我正在尝试使用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 add表单。然后,我创建一个函数来验证表单。最后,我将表单的提交按钮的click事件绑定到验证表单。

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

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

因此,jQuery变量在尝试删除它时不识别它的查询的匹配元素,因为它们在首次分配变量时不存在。如果一个jQuery变量HAD AN eval() METHOD会重新评估其包含的查询以查看是否有任何新的DOM元素匹配它,那将是很好的。但是唉...

有什么建议吗?

提前致谢!

3 个答案:

答案 0 :(得分:8)

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

如果您确实想要更新任意jQuery对象,可以从.selector获取用于创建对象的选择器:

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

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

但是,请注意,如果您在初始选择器之后修改了集合(addfilterchildren等函数),或者jQuery对象是在没有创建的情况下创建的使用选择器(通过传递DOMElement),然后.selector几乎没用,因为选择器将为空,不正确甚至可能无效。

更好的方法是重构您的代码,使您不会持久化jQuery对象;其他答案提出了一些很好的建议。

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

答案 1 :(得分:7)

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

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

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

答案 2 :(得分:4)

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

  1. 避免使用全局变量

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

  2. 请勿使用提交按钮点击事件来检测表单提交。

    如果通过js调用$("form").submit();或输入密钥提交表单怎么办?

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

  4. .live已弃用。请改用.on

  5. 它将解决您的实际问题,但我强烈建议解决所有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");
    });
    
相关问题