Parsley.js Dynamic messages in custom validator - javascript

I'm using a custom validator to check for date of birth, so far it has almost nothing, but I'm trying to add a dynamic message depending on the error and it's not working for me it displays the container with a blank message, any ideas?
Here's the piece of code the custom validator:
window.Parsley.addValidator('age', {
validate: function(value, id){
switch(id){
case 'main':
var day = $('#birthdate_day').val();
var month = $('#birthdate_month').val();
var year = $('#birthdate_year').val();
if(!day || !month || !year){
window.Parsley.addMessage('en', 'age','Error1 ');
return false;
} else {
window.Parsley.addMessage('en', 'age','Error 2');
}
break;
}
return true;
},
messages: {
en: 'Default error',
}
});
Another thing I've tried is setting the data-parsley-age-message="error" during the execution of the validation, but it only shows the error the second time the validation is ran.
Thanks in advance.
EDIT1:
window.Parsley.addValidator('age', {
validate: function(value, id){
$('.birthdate_container').find('ul').remove();
switch(id){
case 'main':
var day = $('#birthdate_day').val();
var month = $('#birthdate_month').val();
var year = $('#birthdate_year').val();
if(!day || !month || !year){
return $.Deferred().reject("One of them is blank");
} else if(day > 2 || month > 2 || year < 2016){
return $.Deferred().reject("Else test of another message");
} else {
return true;
}
break;
}
return true;
},
});
A little cleaner solution (don't mind the else, it's there just for testing) but can't still make it work becasue I don't know how I can update the classes of the 3 elements on returning true.
EDIT 2:
Just using jQuery to handle the classes work, however, since I need to remove the ul (otherwise the messages will stack and I don't want that), whenever there's an error triggered AFTER another error is in there, it simply erases it.
window.Parsley.addValidator('age', {
validate: function(value, id){
$('.birthdate_container').find('ul').remove();
switch(id){
case 'main':
var day = $('#birthdate_day').val();
var month = $('#birthdate_month').val();
var year = $('#birthdate_year').val();
if(!day || !month || !year){
$('.birthdate_container').find('.parsley-success').removeClass('parsley-success').addClass('parsley-error');
return $.Deferred().reject("Un campo es blanco");
} else if(day > 2 || month > 2 || year < 2016){
$('.birthdate_container').find('.parsley-success').removeClass('parsley-success').addClass('parsley-error');
return $.Deferred().reject("dia > 2 o mes > 2 o años < 2016");
} else {
$('.birthdate_container').find('.parsley-error').removeClass('parsley-error').addClass('parsley-success');
return true;
}
break;
}
return true;
},
});

It's not well documented, but you can return an error message from your validator by returning a rejected promise. Check this example.

After too much tinkering with it, I think I got it, I have to reset all the previous parsley so it could rewrite the message if needed, even if it's the same one
window.Parsley.addValidator('age', {
validate: function(value, id){
switch(id){
case 'main':
var container = $('.birthdate_container');
container.find('ul').remove();
var day = $('#birthdate_day');
day.parsley().reset();
var month = $('#birthdate_month');
month.parsley().reset();
var year = $('#birthdate_year');
year.parsley().reset();
if(day.val() === '' || month.val() === '' || year.val() === ''){
container.find('.dropdown').removeClass('parsley-success').addClass('parsley-error');
return $.Deferred().reject("Un campo es blanco");
} else if(day.val() > 2 || month.val() > 2 || year.val() < 2016){
container.find('.dropdown').removeClass('parsley-success').addClass('parsley-error');
return $.Deferred().reject("dia > 2 o mes > 2 o años < 2016");
} else {
container.find('.dropdown').removeClass('parsley-error').addClass('parsley-success');
return true;
}
break;
}
return true;
}
});
PD: Again, the second else is just there to test that you can throw a different message; the validation itself is irrelevant.

My final work:
window.Parsley.addValidator('age', {
validate: function(value, id, instance){
var container = instance.$element.closest('.form-item');
container.find('ul').remove();
var msg = '';
var day = container.find('select').filter(function() {return this.id.match(/\w*birthdate_day/);});
var month = container.find('select').filter(function() {return this.id.match(/\w*birthdate_month/);});
var year = container.find('select').filter(function() {return this.id.match(/\w*birthdate_year/);});
day.parsley().reset();
month.parsley().reset();
year.parsley().reset();
var helpContainer = '<ul class="parsley-errors-list filled"><li class="parsley-age"></li></ul>';
if(value === ''){
container.find('select').parent().addClass('parsley-error');
msg = "This field is required";
}
/* Take several notes here
1) I wrap my select in a div, for stylying purposes, so I check the default placeholder, when something is selected
this placeholder is changed with the value of the select (this is not shown here, it's done elsewhere)
2) I use DD - MM - YYYY as placeholders, if any of these place holders are already showing in the div,
then I don't validate them because they are still 'clean'
3) If the user clicks the submit button though, I set a js variable with this action and then validate the value anyways
because I don't allow blank dates, however, I can't use the parsley-required feature as it messes up my validation
*/
else if(obj.action !== 'submit' && (day.parent().attr('data-placeholder') === 'DD' ||
month.parent().attr('data-placeholder') === 'MM' ||
year.parent().attr('data-placeholder') === 'YYYY'))
{
container.find('select').parent().removeClass('parsley-error')
container.find('select').filter(function(){ return this.value}).parent().addClass('parsley-success');
return true;
}
else if(day.val() === '' || month.val() === '' || year.val() === '') {
container.find('select').parent().addClass('parsley-error');
msg = "This field is required";
}
/*
I have another validation process past this point that uses a different error, but I'll point out the very basic
which is just make some other validation and fill the message you want to display.
Let's assume you want the person not to be underage and you control that in your form somehow
*/
else if (!underageAllowed){
var bdate = String("00" + day.val()).slice(-2) + "/" + String("00" + month.val()).slice(-2) + "/" + year.val();
var tdate = moment(); // Today
bdate = moment(bdate,'DD/MM/YYYY');
var age = tdate.diff(bdate, 'years');
if(age < 18){
container.find('select').parent().addClass('parsley-error');
msg = "Only people with over 18 years old are allower";
}
}
if(msg !== ''){
if(obj.action === 'submit'){
container.append(helpContainer);
container.find('.parsley-age').html(msg)
}
return $.Deferred().reject(msg);
} else {
container.find('select').filter(function(){ return this.value}).parent().addClass('parsley-success');
return true;
}
},
});
I then assign the validator to every field that has "birthdate_" as an id (birthdate_day, birthdate_month and birthdate_year)
$("[id^='birthdate_']").attr('data-parsley-age','true')
.attr('data-parsley-trigger', "change")
.attr('data-parsley-validate-if-empty', "true");
Proper errorContainer for each of the fields
$('#main_form').parsley({
errorsContainer: function(el){
if(el.$element.is('[data-parsley-age]'))
return el.$element.closest('.form-item');
},
And finally how I have my html layout
<div class="form-item">
<label>Date of birth</label>
<div class="dropdown" data-placeholder="DD">
<select id="birthdate_day" name="birthdate_day">
<option value="">-</option> //If user selects this, the validation throws error for all the fields
//Options 1 through 31
</select>
</div>
<div class="dropdown" data-placeholder="MM">
<select id="birthdate_month" name="birthdate_month">
<option value="">-</option> //If user selects this, the validation throws error for all the fields
//Options 1 through 12
</select>
</div>
<div class="dropdown" data-placeholder="YYY">
<select id="birthdate_year" name="birthdate_year">
<option value="">-</option> //If user selects this, the validation throws error for all the fields
//Options 1 through 12
</select>
</div>
Hope this helps out anyone, it took me some time to come up with all this.

If you ONLY want to deal with dynamic messages, do not include a message text in your messages object, then in your validation method:
instance.addError('en', {message: 'Hello World'});
It's as simple as that. Just read the annotated source code and it will unveil a whole host of simple features.
EDIT: actually I just noticed you do need something or it throws it's own error message, so you can fix that with something like:
messages: {
en: '...'
}
I just tested and that works fine

Related

JavaScript validate at least one radio is checked

I'm building a tabbed for using a mixture of JavaScript and CSS. So far I have validation on my text inputs that ensure a user can't progress unless data has been input.
I have got it working so that my script detected unchecked radios, but the problem is that I want the user to only select one. At the moment even when one gets selected the script won't let you progress because it's seeing the other three as unchecked. How could I add a rule to look at the radios and set valid = true if one is selected - if more or less than 1 then fail?
my function:
function validateForm() {
// This function deals with validation of the form fields
var x, y, i, valid = true;
x = document.getElementsByClassName("tab");
y = x[currentTab].getElementsByTagName("input");
// A loop that checks every input field in the current tab:
for (i = 0; i < y.length; i++) {
// If a field is empty...
if (y[i].type === "text") {
if (y[i].value == "") {
// add an "invalid" class to the field:
y[i].classList.add('invalid');
// and set the current valid status to false:
valid = false;
} else if (!y[i].value == "") {
y[i].classList.remove('invalid');
valid = true;
}
}
if (y[i].type === 'radio') {
//y[i].classList.remove('invalid');
//valid = true;
if (!y[i].checked) {
y[i].classList.add('invalid');
valid = false;
} else {
y[i].classList.remove('invalid');
valid = true;
}
}
}
// If the valid status is true, mark the step as finished and valid:
if (valid) {
document.getElementsByClassName("step")[currentTab].className += " finish";
}
return valid; // return the valid status
}
Do I need to split the validation down into further functions to separate validating different field types?
I think that radio buttons are the way to go. Especially from a UI point of view. Why would you let the user pick more than one item only to tell them later they can't?
Having said that, you can do what you're trying to do with something like this:
function validateForm() {
var checkBoxHolders = document.querySelectorAll(".checkboxholder");
var valid = true;
for (var i = 0; i < checkBoxHolders.length; i++) {
var numChecked = checkBoxHolders[i].querySelectorAll("input[type='checkbox']:checked").length;
if (numChecked === 1) {
checkBoxHolders[i].classList.remove('invalid');
} else {
checkBoxHolders[i].classList.add('invalid');
}
valid = valid && numChecked === 1;
}
document.getElementById('valid').innerHTML = 'I am valid: ' + valid;
}
.invalid {
background-color: orange;
}
<input type="text" id='foo'>
<input type="text" id='bar'>
<div class='checkboxholder'>
First group
<input type="checkbox" id='check1'>
<input type="checkbox" id='check2'>
</div>
<div class='checkboxholder'>
Second group
<input type="checkbox" id='check3'>
<input type="checkbox" id='check4'>
</div>
<button type='button' onclick='validateForm()'>Validate me</button>
<div id='valid'>
</div>
With jQuery, it'd be something like:
if (jQuery('input[name=RadiosGroupName]:checked').length === 0) {
valid = false;
}

How can I check if textarea (tinymce) only contains space?

I have a form using Tinymce, I need to check if it only contains space.
I try using this function
function validation_form()
{
var content = tinyMCE.get('main-comment').getContent().replace(' ','');
if(content == "" || content == null || content == '<p> </p>') {
return false;
}
}
But it returns true when I input several spaces and submit, I want it to return false instead.
Can anyone help me?
Thanks,
use $.trim ,
it is clean and readable.
function validation_form()
{
var content = $.trim(tinyMCE.get('main-comment').getContent({format: 'text'}));
if(content.length == 0) {
return false;
}
return true;
}
Updated: format as text, to get text content from editor. check fiddle
-- Originally wrote it in PHP --
function validation_form()
{
var content = $.trim(tinyMCE.get('main-comment').getContent());
if(content.length == 0) {
return false;
}
return true;
}
Is Correct #A.T
You can use javascript's trim method.
function validation_form()
{
var content = tinyMCE.get('main-comment').getContent().replace(' ','').trim();
if(content == "" || content == null || content == '<p> </p>') {
return false;
}
}
For more information, please check here
Solution for the same while using Angular Reactive Form Validation
Give this custom validator function in typescript file
emptyLinesValiadtor(control:FormControl):{[s:string]:boolean} | null {
let content = control.value.replaceAll(/ /gm,'')
.trim().split(" ").join("").replaceAll('<p></p>','').trim();
if(content == "" || content == null) {
return {'emptyLines': true}
}
return null;
}
In your Reactive form builder/declaration
this.formName= this.formBuilder.group({
textArea:['',this.emptyLinesValiadtor]
});
In your template form
<div
*ngIf="sForm.submitted && f.textArea.errors">
<div *ngIf="f.textArea.errors.emptyLines">
<div>Answer cannot contain empty lines/spaces</div>
</div>
</div>
where sform is reference variable and f is a typescript get method like below
get f() {
return this.formName.controls;
}

how to add one error instead of multiple errors

Hi I have designed my form now i am unsure how to combine all the alert messages instead of them popping up one at a time , please could someone tell my how to do this in simple terms as i am new to javascript. thankyou in advance. below is my script.
function validateForm() {
// this part of the script will collate all errors into one should the user leave an input blank
var Fname=document.forms["myForm"]["fname"].value;
var Lname=document.forms["myForm"]["lname"].value;
var address=document.forms["myForm"]["addr1"].value;
var postcode=document.forms["myForm"]["pcode"].value;
var email=document.forms["myForm"]["email"].value;
var number=document.forms["myForm"]["tel"].value;
var date=document.forms["myForm"]["mydate"].value;
if (Fname==null || Fname=="" ||Lname==null || Lname=="" ||address==null || address=="" ||!postcode||!email||!number||( myForm.sex[0].checked == false ) && ( myForm.sex[1].checked == false )||(myForm.age[0].checked == false )&&(myForm.age[1].checked == false )&&(myForm.age[2].checked == false )&&(myForm.age[3].checked == false )&&(myForm.age[4].checked == false )||!date)
{
alert("Please make sure all fields are filled or checked correctly out ");
return false;
}
//end of collating script
//start of postcode script
var regPostcode = /^[a-zA-Z]{1,2}\d[\dA-Za-z]? \d[a-zA-Z]{2}$/;
if (!postcode.match(regPostcode))
{
alert("That Post Code is incorrect, correct way mk4 4tr");
return false;
}
//end of postcode script
//start of email script
var regEmail =/^\S+#\S+\.\S+$/;
if (!email.match(regEmail))
{
alert("That email is incorrect");
return false;
}
// end of email script
// start of phone number script
var phonestring = /^(?:0|\+44)[12378]\d{8,9}$/;
if (!number.match(phonestring))
{
alert(" incorrect,correct format 01908234874");
return false;
}
// end of phone script
//start of gender script
if ( ( myForm.sex[0].checked == false ) && ( myForm.sex[1].checked == false ) )
{
alert ( "Please choose your Gender: Male or Female" );
return false;
}
// end of gender script
//start of age group script
if((myForm.age[0].checked == false )&&(myForm.age[1].checked == false )&&(myForm.age[2].checked == false )&&(myForm.age[3].checked == false )&&(myForm.age[4].checked == false )){
alert("please select an age group");
return false;
}
// end of age script
//start of datefield
var dateformat=/^(?:(?:31\/(?:0[13578]|1[02])|(?:29|30)\/(?:0[13-9]|1[012])|(?:0[1-9]|1\d|2[0-8])\/(?:0[1-9]|1[0-2]))\/[2-9]\d{3}|29\/02\/(?:[2-9]\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[3579][26])00))$/;
if (!date.match(dateformat))
{
alert("format incorrect use dd/mm/yyyy make sure you are entering correct days to the month remember 30 days have september, april, june & november, only 28 days in february unless leap year next is 2016");
return false;
}
var today = new Date();
var courseYear =date.substr(6,4) // use substr or substring to capture the last four digits
var courseMonth =date.substr(3,2) // use substr or substring to capture the four and fifth digits
var courseDay = date.substr(0,2)//e the first and second digits
var dateToCompare = new Date(courseYear, courseMonth, courseDay);
if (dateToCompare < today) {
alert("this date is in the past");
return false; }
//end of date field
else
{ alert(" Thank you a member of our team will get back to you shortly");
return true;}
}
create some kind of collection that you can append to and instead of alerting independantly, just add them to the set. Something like:
function validateForm(){
var errors = []; // new array to hold all the errors
/*
validation code that instead of
alert('error')
use
errors.push('error');
Also remove any premature `return` statements and
leave them until the end.
*/
// next check if there are errors
if (errors.length > 0){
// display them
alert('Following errors found:\n- ' + errors.join('\n- '));
// also return false to flag there was a problem
return false;
}
// if we reached this code there were no errors
return true;
}
Add all your errors to an array and then alert them at the end, if any exist:
function validateForm() {
var errors = []; //array for holding errors
.
.
.
if (Fname==null || Fname=="" ||Lname==null || Lname=="" ||address==null || address=="" ||!postcode||!email||!number||( myForm.sex[0].checked == false ) && ( myForm.sex[1].checked == false )||(myForm.age[0].checked == false )&&(myForm.age[1].checked == false )&&(myForm.age[2].checked == false )&&(myForm.age[3].checked == false )&&(myForm.age[4].checked == false )||!date) {
errors.push("Please make sure all fields are filled or checked correctly out "); //add error
}
//end of collating script
//start of postcode script
var regPostcode = /^[a-zA-Z]{1,2}\d[\dA-Za-z]? \d[a-zA-Z]{2}$/;
if (!postcode.match(regPostcode)) {
errors.push("That Post Code is incorrect, correct way mk4 4tr"); //add error
}
//end of postcode script
//start of email script
var regEmail =/^\S+#\S+\.\S+$/;
if (!email.match(regEmail)) {
errors.push("That email is incorrect"); //add error
}
if(errors.length > 0) {
alert('The following errors occurred: ' + errors.join('\n')); //alert errors if they exist
return false;
}
return true; // allow submit
}

Check if placeholder text already exists within a string

I have an #error paragraph. Everytime there is an error within the form on submit. The inputs placeholder text gets added to the #error paragraph.
My problem:
It happens everytime a user clicks submit. So the #error message returns:
Please fill in yourfirst name, last name, company, position, first
name, last name, company, position, first name, last name, company,
position, first name, last name, company, position, first name, last
name, company, position, first name, last name, company, position,
I've looked for other solutions and tried this:
if (input.attr('placeholder').indexOf($('#error')) >= 0){
} else{
$('#error').append(input.attr('placeholder').toLowerCase() + ', ');
}
Is there any way to check if the placeholder text already exists in the #error message? Here's a fiddle. I'm sorry it's so convoluted. But its what i've been working on and had it handy.
Thanks for your help in advance!
http://jsfiddle.net/8YgNT/20/
var errorText = '';
//Validate required fields
for (i = 0; i < required.length; i++) {
var input = $('#' + required[i]);
if ((input.val() == "") || (input.val() == emptyerror)) {
input.addClass("tobefixed");
errornotice.fadeIn(750);
if (input.attr('placeholder').indexOf($('#error')) >= 0) {
// do nothing
} else {
errorText = errorText + $(input).attr('placeholder').toLowerCase() + ', ';
}
input.val(emptyerror);
errornotice.fadeIn(750);
} else {
input.removeClass("tobefixed");
}
}
$('#error').html('').append('Please fill in your ' + errorText);
I simple add one line in your fiddle and it's working now:
required = ["id_first_name", "id_last_name", "id_firmbox", "id_job_title"];
errornotice = $("#error");
emptyerror = "Please fill out this field.";
$("#startform").submit(function(){
//Validate required fields
$("#error").html("Please fill in your");
for (i=0;i<required.length;i++) {
var input = $('#'+required[i]);
if ((input.val() == "") || (input.val() == emptyerror)) {
input.addClass("tobefixed");
errornotice.fadeIn(750);
// =====Here===== //
if (input.attr('placeholder').indexOf($('#error')) >= 0){
} else{
$('#error').append(input.attr('placeholder').toLowerCase() + ', ');
}
// ============== //
input.val(emptyerror);
errornotice.fadeIn(750);
} else {
input.removeClass("tobefixed");
}
}
if ($(":input").hasClass("tobefixed")) {
return false;
} else {
errornotice.hide();
return true;
}
});
$(":input").focus(function(){
if ($(this).hasClass("tobefixed") ) {
$(this).val("");
$(this).removeClass("tobefixed");
}
});
This line do the all trick:
$("#error").html("Please fill in your");
Saludos ;)
If you want to check whether #error contains the string you're wondering about, you can use
($('#error').text().indexOf(a_string)) != -1
This will return true if #error contains a_string.
There's a longer discussion on searching strings for other strings in this question.
It seems you're doing it the wrong way round (and forgetting to get the text out of the #error element):
if ( $('#error').text().indexOf( input.attr('placeholder') ) >= 0)

jquery custom validation script without plugin?

i used to use jquery validation plugin but because of lack of this plugin with wysiwyg plugins i wrote a simple script to validate my form
i tried to do it like this
function validateArticle(formData, jqForm, options) {
$('#errors').empty();
if ($('#editor').val() == 0) {
$('#errors').show();
$('#errors').append('<li>please enter your article body</li>');
return false;
}
if ($('#ArticleTitle').val() == 0) {
$('#errors').show();
$('#errors').append('<li>please enter your article title</li>');
return false;
}
$('#errors').hide();
return true ;
}
i found to 1 problem when it validate the form it's validating it field by field so the errors messages doesn't appear at once
i tried to do something like
var errors = [];
function validateArticle(formData, jqForm, options) {
$('#errors').empty();
if ($('#editor').val() == 0) {
errors.push('<li>please enter your article body</li>');
var invalid = 1 ;
return false;
}
if ($('#ArticleTitle').val() == 0) {
errors.push('<li>please enter your article title</li>');
var invalid = 1 ;
return false;
}
if(invalid == 1){
$.each(errors , function(i, val) {
$('#errors').append(errors [i]);
});
}
$('#errors').hide();
return true ;
}
i tried to push errors as array elements and loop through them in case of invalid is true
bu this one doesn't work at it all ?
is there any way to make it work ?
if ($('#editor').val() == 0) // This is checking if value is 0
This does not make sense..
Try
if ($('#editor').val() == '') //Instead check for empty string
EDIT
Also you seem to be hiding the error's div in the end.
$('#errors').hide();
Try this code Instead
$('#validate').on('click', function() {
var errors = [];
var html = '<ul>' ;
valid = true;
$('#errors').empty();
if ($('#editor').val() == '') {
errors.push('<li>please enter your article body</li>');
valid = false;
}
if ($('#ArticleTitle').val() == '') {
errors.push('<li>please enter your article title</li>');
valid = false;
}
if (!valid) {
html += errors.join('') + '</ul>'
$('#errors').append(html);
}
else{
$('#errors').hide();
}
return valid;
});​
DEMO

Categories