0

I am using jquery validation to validate a form. I am trying to accomodate a designer's whim and it is proving rather tricky. Basically the designer wants blue text "required*" for each mandatory input. If a mandatory input is not completed then the blue text should turn to red text i.e. only the color changes and the text remains the same.

I have put the blue text in a label with class "mandatory"

<label class="mandatory">required*</label>

I have also set all jquery validation required messages to the same "required*" text as in the label above. The plan is to hide the blue label and show the error label if it does not validate.

Here is where I feel I am doing something a bit stupid - In errorplacement and success I am running the following code:

errorPlacement: function (error, element) {
  element.siblings(".mandatory").hide();
  error.insertBefore(element.prev());
},
success: function (element) {
  element.siblings("label.errorMessage").remove();
  element.siblings(".mandatory").show();
}

However, this all works fine when the form is submitted - the blue label is successfully hidden and the error label is placed in the correct position.

If the user adds text to one of the error inputs then the "success function" above is executed properly and error label is hidden whilst the blue label is made visible.

If the user deletes the text from the same input that he just added text to, the input is validated individually and the error label is shown and this is where the issue is... the errorplacement code does not seem to execute again and now I have both blue and red labels visible.

Anyone know what I can do to hide the blue label at the point the input is validated again - BTW if the form is submitted again then all is fine?

Cheers

Wing

wingyip
  • 3,465
  • 2
  • 34
  • 52

4 Answers4

1

I don't believe it's possible to display the error message when the field has passed validation. Internal to the plugin is the code that makes all the labels hidden when the field passes validation. I see you may just be trying to simulate the effect though.

If you want to play around with this, I'll provide some insight that may ultimately take you to a solution.

Look at the highlight and unhighlight callbacks. These complementary functions were designed for such things as showing pass/fail icons, etc.

Here they are with their default code:

    highlight: function (element, errorClass, validClass) {
        if (element.type === "radio") {
            this.findByName(element.name).addClass(errorClass).removeClass(validClass);
        } else {
            $(element).addClass(errorClass).removeClass(validClass);
        }
    },
    unhighlight: function (element, errorClass, validClass) {
        if (element.type === "radio") {
            this.findByName(element.name).removeClass(errorClass).addClass(validClass);
        } else {
            $(element).removeClass(errorClass).addClass(validClass);
        }
    },

Here is the default errorPlacement callback:

    errorPlacement: function (error, element) {
        error.insertAfter(element);
    },

The success callback has no default, but as per docs, you can use it to place text in the label upon success.

    success: function (label) {
        label.removeClass('error').addClass('valid').text('ok')
    },

Since error and valid are the default CSS class's for the label & elements, you perhaps can leverage their colors like this...

label.valid {
    color: #00f;
}

label.error {
    color: #f00;
}

Here is a jsFiddle that you can use for testing: http://jsfiddle.net/7TPvP/

This is the documentation on all the callback functions and options: http://docs.jquery.com/Plugins/Validation/validate#toptions


Some notes on your code:

Quote OP:

"the errorplacement code does not seem to execute again and now I have both blue and red labels visible."

That is because the actual label (created by the plugin for the error) has already been placed once. No need to place it again. If you want something to continually fire on & off, look at the highlight and unhighlight callback functions.


EDIT:

Here is something very close to what you want. You'll still need to tweak it a bit...

DEMO: http://jsfiddle.net/2mwfG/

$(document).ready(function () {

    $('#myform').validate({ // initialize the plugin
        // other options and rules,
        highlight: function (element, errorClass, validClass) {
            if (element.type === "radio") {
                this.findByName(element.name).addClass(errorClass).removeClass(validClass);
            } else {
                $(element).addClass(errorClass).removeClass(validClass);
                $(element).prev('.mandatory').hide(); // <-- added this
            }
        },
        unhighlight: function (element, errorClass, validClass) {
            if (element.type === "radio") {
                this.findByName(element.name).removeClass(errorClass).addClass(validClass);
            } else {
                $(element).removeClass(errorClass).addClass(validClass);
                $(element).prev('.mandatory').show();  // <-- added this
            }
        },
        errorPlacement: function (error, element) {
            error.insertAfter(element);
        }
    });

});
Sparky
  • 98,165
  • 25
  • 199
  • 285
  • Hi there - just a quick one before I wade throgh the rest - have used error.insertBefore(element.prev()) because the html is
    - I needed to insert before the
    – wingyip Feb 28 '13 at 21:30
  • @wingyip, ok... feel free to use whatever error placement code works for you. – Sparky Feb 28 '13 at 21:40
  • 1
    Think I've cracked it http://jsfiddle.net/ANUKs/42/ - Sparky put me on the right track - Thanks – wingyip Mar 01 '13 at 00:15
1

I haven't used jQuery validation much but I think I see what you're trying to do and I have a suggestion to make it easier, and it may also fix the issues you're having... instead of hiding and showing 2 different labels on error or success why not just use the one label and toggle an "error" class on and off depending on the outcome of the validation? something like this might do the trick:

errorPlacement: function (error, element) {
  element.siblings(".mandatory").addClass('error');
},
success: function (element) {
  element.siblings(".mandatory").removeClass('error');
}

Your label will be blue by default due to the "mandatory" css rule and you can write a style for the "error" class that will make it turn red when the class is applied. This way you're not fumbling around with adding and removing labels, you'll only ever have the one that just toggles state.

I hope that helps.

gbinflames
  • 2,812
  • 1
  • 16
  • 8
  • Please try it in a jsFiddle. This will not work because: 1. that's not how those two callback functions will fire. 2. `siblings()` will target them all at once. 3. This will break the default error messages toggled by the plugin. – Sparky Feb 28 '13 at 17:50
0

Perhaps rather than removing and inserting the error message into the DOM you could have it there all along and just show or hide it like you are doing for the mandatory message?

So include it in your html but hide it.

<span class="errorMessage" style="display: none;">* required</span>

then you can just display it or hide it with your current code:

errorPlacement: function (error, element) {
  element.siblings(".mandatory").hide();
  element.siblings(".errorMessage")show();
},
success: function (element) {
  element.siblings(".errorMessage").hide();
  element.siblings(".mandatory").show();
}
JeffJenk
  • 2,575
  • 2
  • 21
  • 28
  • Since he showed his HTML code for this `mandatory` label, he seems to already be doing this. – Sparky Feb 28 '13 at 16:03
0

Firstly - you say the errorPlacement callback does not seem to execute again. It doesn't. It only executes once per field in the lifecycle of the plugin. This is say, once it has made the errorLabel and placed it in the page its job is done.

You could manually put in the error label as described in this answer

<label for="name" class="error" generated="true">your message here</label>

However, the plugin will delete the inner text of the label when the field is valid.

Try this then, I have stashed the error message in a data- attribute, and retrieved it in the success callback if it is present.

<input name="one" id="one" class="required" />
<label data-message="* this is required" for="one" class="error valid"></label>

script is below fiddle is here

$(function () {

    $('label[data-message]').each(function () {
        $(this).html($(this).data("message"));
    });

    $("form").validate({
        success: function (label) {
            if (label.data("message")) {
                label.addClass("valid").text(label.data("message"));
            } else {
                label.text("");
            }
        },
        submitHandler: function () {
            alert('form is ok');
        }
    });
});
Community
  • 1
  • 1
politus
  • 5,996
  • 1
  • 33
  • 42