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'
    }
});
Ingvi Jónasson
  • 730
  • 8
  • 27

3 Answers3

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.

Thanasis1101
  • 1,614
  • 4
  • 17
  • 28
  • 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) – Vivek Athalye Feb 25 '17 at 16:17
  • Oh yes, I didn't notice this. Wait and I will solve this. – Thanasis1101 Feb 25 '17 at 16:19
  • Ok, I corrected it. See [here](http://codepen.io/anon/pen/WpbzBx). I will also update my answer. – Thanasis1101 Feb 25 '17 at 16:24
  • 1
    +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 :) – Vivek Athalye Feb 25 '17 at 16:32
  • @Ingvi was the answer helpful? If not, tell me what else you wanted. If yes, consider marking my answer as accepted. Thanks :) – Thanasis1101 Feb 25 '17 at 18:26
  • 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? – Ingvi Jónasson Feb 25 '17 at 20:45
  • I have an idea on how to do it. I'll let you know when I reach to the solution. – Thanasis1101 Feb 25 '17 at 20:49
  • See my new [Codepen](http://codepen.io/anon/pen/jBEvvZ) and let me know if you are satisfied, in order to fully update my answer. – Thanasis1101 Feb 25 '17 at 21:08
  • Thanks for the effort Thanasis, I will have a look tomorrow morning. – Ingvi Jónasson Feb 26 '17 at 10:59
  • 1
    Thanks for marking as accepted ! I also added to my answer the neccessary code from the codepen, and a little explanation. – Thanasis1101 Feb 27 '17 at 16:21
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

Community
  • 1
  • 1
Jaffer Wilson
  • 7,029
  • 10
  • 62
  • 139
  • 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. – Ingvi Jónasson Feb 25 '17 at 15:16
  • @Ingvi Sure .. Thank you for your clarifcation. I will let you know. Finding your query more interesting. – Jaffer Wilson Feb 25 '17 at 15:22
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;
            }                
        });
}
Shahar Shokrani
  • 7,598
  • 9
  • 48
  • 91