最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Getting an assigned jQuery variable to "re-query" - Stack Overflow

programmeradmin5浏览0评论

I'm trying to use jQuery to build a home-made validator. I think I found a limitation in jQuery: When assigning a jQuery value to a json variable, then using jQuery to add more DOM elements to the current page that fit the variable's query, there doesn't seem to be a way to access those DOM elements added to the page which fit the json variable's query.

Please consider the following code:

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...
        }
    });
})

An example is availible here: /

First, I make a json variable to represent the html add form. Then, I make a function to validate the form. Last, I bind the click event of the form's submit button to validating the form.

Notice that I'm using the jQuery after() method to put a span containing an '*' after every invalid field label in the form. Also notice that I'm clearing the asterisks of the previous submission attempt from the form before re-validating it (this is what fails).

Apparently, the call to add_form.$errors.remove(); doesn't work because the $errors variable only points to the DOM elements that matched its query when it was created. At that point in time, none of the labels were suffixed with error_marker variable.

Thus, the jQuery variable doesn't recognize the matching elements of it's query when trying to remove them because they didn't exist when the variable was first assigned. It would be nice if a jQuery variable HAD AN eval() METHOD that would re-evaluate its containing query to see if any new DOM elements matched it. But alas...

Any suggestions?

Thanks in advance!

I'm trying to use jQuery to build a home-made validator. I think I found a limitation in jQuery: When assigning a jQuery value to a json variable, then using jQuery to add more DOM elements to the current page that fit the variable's query, there doesn't seem to be a way to access those DOM elements added to the page which fit the json variable's query.

Please consider the following code:

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...
        }
    });
})

An example is availible here: http://jsfiddle/Macxj/3/

First, I make a json variable to represent the html add form. Then, I make a function to validate the form. Last, I bind the click event of the form's submit button to validating the form.

Notice that I'm using the jQuery after() method to put a span containing an '*' after every invalid field label in the form. Also notice that I'm clearing the asterisks of the previous submission attempt from the form before re-validating it (this is what fails).

Apparently, the call to add_form.$errors.remove(); doesn't work because the $errors variable only points to the DOM elements that matched its query when it was created. At that point in time, none of the labels were suffixed with error_marker variable.

Thus, the jQuery variable doesn't recognize the matching elements of it's query when trying to remove them because they didn't exist when the variable was first assigned. It would be nice if a jQuery variable HAD AN eval() METHOD that would re-evaluate its containing query to see if any new DOM elements matched it. But alas...

Any suggestions?

Thanks in advance!

Share Improve this question asked Jun 4, 2012 at 1:58 Nautic20Nautic20 2154 silver badges15 bronze badges 6
  • That's not JSON, it's an object. (JSON is a string representation of an object.) – nnnnnn Commented Jun 4, 2012 at 2:03
  • Use upper case function names if the function can used a constructor for objects. ValidateForm() implies that you can do new ValidateForm which you can't so name it validateForm. – d_inevitable Commented Jun 4, 2012 at 2:22
  • Also .live is deprecated. Use .on instead. – d_inevitable Commented Jun 4, 2012 at 2:24
  • 1 Rather than adding and removing the asterisk spans, have you considered having them beside all mandatory fields in the first place but then hiding and showing them from your JS/jQuery code? (Whether with the .hide() and .show() methods or by adding/removing classes?) In my opinion the fact that jQuery objects don't automatically update themselves when the DOM changes is a good thing for most purposes. – nnnnnn Commented Jun 4, 2012 at 2:37
  • Thanks d_inevitable and nnnnnn! Very good advice from the both of you. I'll definitely take it to heart. – Nautic20 Commented Jun 4, 2012 at 15:06
 |  Show 1 more ment

3 Answers 3

Reset to default 8

You are correct that a jQuery object is not "live" – that is, the set of elements in the jQuery object is not dynamically updated. (This is a good thing.)

If you really want to update an arbitrary jQuery object, you can get the selector used to create the object from .selector:

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

So you could do els = $(els.selector); to re-query the DOM.

Note, however, that if you modified the collection after the initial selector (functions like add, filter, children, etc.), or if the jQuery object was created without using a selector (by passing a DOMElement), then .selector will be pretty much useless, since the selector will be empty, incorrect, or even potentially invalid.

Better is to re-structure your code in such a way that you aren't holding on to a stale jQuery object; the other answers make some good suggestions.

Also, please make sure you're validating input server-side too!

For the objects that are going to be changing, instead of making the JSON object reference a static value, make it a function:

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

since it's a function, it will re-evaluate the error fields every time you call add_form.$errors().

Your approach to the problem has got many structural problems:

  1. Avoid using global variables

    There may not always be just one form on the page that you are validating. What if one day you will decide that you will have several forms. Your add_form variable is a global variable and therefore would be conflicting.

  2. Do not use the submit button click event for detecting form submissions.

    What if a form is submitted by a js call like $("form").submit(); or by the enter key?

  3. Store the selectors instead of the DOM objects if you are not certain that the objects already exist at the creation time of the configuration object.

  4. .live is deprecated. Use .on instead.

It is 3. that will solve your actual problem, but I strongly remend addressing all 4 issues.

For 2, the best place to attach the validator is not on the submit button, but on submit event of the form. Something like this:

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

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

Note how the form is now also much easier to access. Your configuration object no longer needs to store a reference to the submit button.

Your configuration object could now be simplified to be something like this:

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

Within validateForm, you can use these selector as follows:

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

Now, to allow different configuration parameters for each form use something like this:

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");
});
发布评论

评论列表(0)

  1. 暂无评论