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

3

6

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

  • Password needs to have at least 8 characters
  • One special character is required
  • One number is required

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'
    }
});
Ratha answered 20/2, 2017 at 12:5 Comment(0)
M
4

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.

Manon answered 25/2, 2017 at 16:6 Comment(10)
Interesting approach. But after entering valid input, if you start pressing backspace, error and success messages are displayed at the same time. (I mean the same message is displayed in green and red color both)Throckmorton
Oh yes, I didn't notice this. Wait and I will solve this.Manon
Ok, I corrected it. See here. I will also update my answer.Manon
+1 for the updated CodePen. Btw, you are not handling 'This value is required' message. But I guess OP will be able to handle it :)Throckmorton
@Ingvi was the answer helpful? If not, tell me what else you wanted. If yes, consider marking my answer as accepted. Thanks :)Manon
Thanasis, your answer is very simple and clean. Thanks a lot. The only problem is that when the error messages are inserted into the .success they are moving up visually. I need them somehow to stay in place. I am wondering if it is possible to save the list position of each item and add them back to the .parsley-errors-list to the same position as where they where before. What do you think?Nicollenicolson
I have an idea on how to do it. I'll let you know when I reach to the solution.Manon
See my new Codepen and let me know if you are satisfied, in order to fully update my answer.Manon
Thanks for the effort Thanasis, I will have a look tomorrow morning.Nicollenicolson
Thanks for marking as accepted ! I also added to my answer the neccessary code from the codepen, and a little explanation.Manon
S
0

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

Surtout answered 25/2, 2017 at 14:51 Comment(2)
Thanks for your answer Jaffer I appreciate your effort. In your answer (and JsFiddle) you are toggling classes on the input field itself. What I am going after is toggling classes on each individual children of the .parsley-error-list. So as an example there might be one validation error with an error class and two validation error with a succesful class and the messages should stay in the dom and not be removed. I hope this makes somehow sense.Nicollenicolson
@Ingvi Sure .. Thank you for your clarifcation. I will let you know. Finding your query more interesting.Surtout
S
0

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;
            }                
        });
}
Sumrall answered 5/9, 2017 at 20:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.