Ingvi Jónasson
Ingvi Jónasson

Reputation: 762

How to prevent form validation errors to be removed from the DOM with Parsleyjs

I am validating a password field with parsleyjs. The password has three requirements and thus three validation messages:

When a validation returns successful I do not want the message to be removed but to stay in place and visually style the message, in this case with a green checkmark ( default the message has a red error icon). So basically want to add a class or remove and keep the message in the DOM.

As an example when one integer has been inserted the validation might look like this:

enter image description here

Is it possible with parsley to prevent the default behavior (removing the message) and add a successful class to a corresponding error message (not just the error list container)?

Here is what I have so far and a codepen demo

$(function() {
    $('.form').parsley();
});

window.Parsley.addValidator('number', {
    validateString: (value) => {
        const format = /\d/;
        return format.test(value);
    },
    messages: {
        en: 'One number is required'
    }
});

window.Parsley.addValidator('specialChar', {
    validateString: (value) => {
        const format = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/;
        return format.test(value);
    },
    messages: {
        en: 'One special character is required'
    }
});

Upvotes: 6

Views: 2429

Answers (3)

Shahar Shokrani
Shahar Shokrani

Reputation: 8762

The @Thanasis answer is ok, but i want to suggest shorter answer (no css).

HTML

<input type="password" 
       data-parsley-number="true" 
       data-parsley-specialchar="true" 
       data-parsley-min8="true" 
       data-parsley-error-message="Password rules are:" 
       data-parsley-required="true">
<ul>
    <li id="number-char">number</li> 
    <li id="special-char">special-char (;,/,?,:,@,&amp;,=,+,$)</li> 
    <li id="min8-char">at least 8 chars</li> 
</ul>

JavaScript:

if (typeof Parsley !== 'undefined') {

    Parsley.addValidator('specialchar',
        function (value){            
            if (/^[a-zA-Z0-9.]*$/.test(value)==false) {
                jQuery("#special-char").addClass("completed");
                return true;
            }
            else {
                jQuery("#special-char").removeClass("completed");
                return false;
            }
        });    
    Parsley.addValidator('number',
        function (value){            
            if (/[0-9]/.test(value)){
                jQuery("#number-char").addClass("completed");
                return true;
            }
            else{
                jQuery("#number-char").removeClass("completed");
                return false;
            }                
        });  
    Parsley.addValidator('min8',
        function (value){            
            if (value.length >= 8){
                jQuery("#min8-char").addClass("completed");
                return true;
            }
            else{
                jQuery("#min8-char").removeClass("completed");
                return false;
            }                
        });
}

Upvotes: 0

Thanasis1101
Thanasis1101

Reputation: 1680

I came up with this solution for your problem which works fine.

You can test it on this Codepen Link.

HTML

<form class="form">
    <label for="password-01">Password:</label>
  <input class="password" id="password-01" type="password" required 
data-parsley-class-handler=".errors"
data-parsley-errors-container=".errors"
data-parsley-special-char="" data-parsley-number="" minlength="8" data-parsley-validation-threshold="0" data-parsley-trigger="keyup" data-parsley-priority-enabled="false"/>
    <input type="submit" value="Submit" />
</form>
<div class="feedback">
    <div class="success"></div>
    <div class="errors"></div>
</div>

CSS

body {
    font-family: sans-serif;
}

.form {
    padding: 1rem;
    background: lightgrey;
}

label {
    display: block;
    margin-bottom: .2rem;
}

.feedback {
    margin-top: 1rem;
    border: 1px solid gray;
    padding: 2rem;
}

.parsley-errors-list {
    list-style: none;
    padding-left: 0;
    margin: 0;
}

.parsley-errors-list li {
    color: red;
}

.success {
    color: green;
}

Javascript

$(function() {
    $('.form').parsley();   

    window.Parsley.addValidator('number', {
        validateString: (value) => {
            const format = /\d/;
            return format.test(value);
        },
        messages: {
            en: 'No number'
        }
    });

    window.Parsley.addValidator('specialChar', {
        validateString: (value) => {
            const format = /[!@#$%^&*()_+\-=[\]{};':"\\|,.<>/?]/;
            return format.test(value);
        },
        messages: {
            en: 'No special character'
        }
    });

    $('.password').on('keyup', function() {

        $('.success').html(""); // clear success div

            // check numbers success
            if (window.Parsley._validatorRegistry.validators.number.validateString($('.password').val())){      
                $('.success').append( window.Parsley._validatorRegistry.validators.number.messages.en +"<br>");
            }


            // check specialChar success
            if (window.Parsley._validatorRegistry.validators.specialChar.validateString($('.password').val())){     
                $('.success').append( window.Parsley._validatorRegistry.validators.specialChar.messages.en +"<br>");
            }

        var length = $('.password').val().length;

            // check if input is empty
            if (length > 0){
                    $('.success').append("This value is required.<br>");
            }

            // check minlength success  
            var minlength = $('.password').attr("minlength");
            if (length >= minlength){
                $('.success').append("This value is too short. It should have "+minlength+" characters or more.<br>");
            }



    });

});

Changes in HTML:

What I did is that I added a div for the green messages (success div), a div for the red messages (errors div) and rearranged the feedback div to this:

<div class="feedback">
    <div class="success"></div>
    <div class="errors"></div>
</div>

Also in the input attributes I replaced this:

data-parsley-class-handler=".feedback"
data-parsley-errors-container=".feedback"

with this:

data-parsley-class-handler=".errors"
data-parsley-errors-container=".errors"

Changes in CSS:

I renamed this CSS part: .parsley-errors-list .success to this: .success.

Changes in Javascript:

In the javascript I added the function window.Parsley.on('field:validate', function() {...}); which is triggered before the check of the validators (see here under Events List). In there I added 4 if statements which check if the numbers validator is correct, if the specialChar validator is correct, if the input is not empty and if the length of the input is bigger or equal to the minlength. If any of these are true then the corresponding message is added to the div success which has the color green for the text. Before adding these, the success div is cleared ($('.success').html("");) in order for the green messages to be updated.


Hope this was helpful. Please let me know if there is something you didn't understand or you wanted it differently.

Sources:

UPDATE

Since you want to make the messages stay in the same position, you can check this Codepen I created. I deleted the errors and success divs from the html, and added the function below in the javascript:

$('.password').on('input', function() {

    $('.feedback').html(""); // clear feedback div

    // check numbers success
    if (window.Parsley._validatorRegistry.validators.number.validateString($('.password').val())){      
        $('.feedback').append("<font color='green'>" + window.Parsley._validatorRegistry.validators.number.messages.en +"</font><br>");
    } else {      
        $('.feedback').append("<font color='red'>" + window.Parsley._validatorRegistry.validators.number.messages.en +"</font><br>");
    }   

    // check specialChar success
    if (window.Parsley._validatorRegistry.validators.specialChar.validateString($('.password').val())){     
        $('.feedback').append("<font color='green'>"+ window.Parsley._validatorRegistry.validators.specialChar.messages.en +"</font><br>");
    } else {
        $('.feedback').append("<font color='red'>"+ window.Parsley._validatorRegistry.validators.specialChar.messages.en +"</font><br>");
    }

    var length = $('.password').val().length;

    // check if input is empty
    if (length > 0){
        $('.feedback').append("<font color='green'>This value is required.</font><br>");
    } else {
        $('.feedback').append("<font color='red'>This value is required.</font><br>");
    }

    // check minlength success  
    var minlength = $('.password').attr("minlength");
    if (length >= minlength){
        $('.feedback').append("<font color='green'>This value is too short. It should have "+minlength+" characters or more.</font><br>");
    } else {
        $('.feedback').append("<font color='red'>This value is too short. It should have "+minlength+" characters or more.</font><br>");
    }   

});

With the function above, every time the input is changed, the feedback div is cleared and then the 4 conditions are checked and the messages are added in the feedback div colored green if the corresponding condition is true or colored red otherwise.

Upvotes: 4

Jaffer Wilson
Jaffer Wilson

Reputation: 7273

Yes you can add the custom CSS while using parsleyjs. See the following:

$('form').parsley();

$.listen('parsley:field:error', function(ParsleyField) {
    ParsleyField.$element.prev('i.fa').removeClass('cta-success').addClass('cta-error');
});
$.listen('parsley:field:success', function(ParsleyField) {
    ParsleyField.$element.prev('i.fa').removeClass('cta-error').addClass("cta-success");    
});

You can see the working example on the JsFiddle Website.

You can also check the example on codepen.io

You can also check the answer of guillaumepotier at the following:

Parsley.js - Displaying Errors in a Specified Element

Upvotes: 0

Related Questions