How to view the ParsleyJS errors without blocking form submition - parsley.js

Is there a way to get the list of errors from parsley.js? I have a form that has one field that I want validate and give feedback to the user as a warning, but I don't want the error state for that field to block form submission. I am handling the form submission myself, so I'm looking for something like
$("form[name='client']").on('submit'), function(e) {
e.preventDefault();
var form = $(this);
form.parsley().validate();
// pseudo code as I don't know how to do this yet with parsley
var errors = form.parsley().errors().filter(function(err) { return err.field != field_to_ignore })
if (errors.length ) {
// error handling
} else {
// submit form
}
});

You could change the inputs or excluded options when you click on submit so that your inputs are all excluded.

My Solution is to work with two validations:
1.The first one is binding the error to the UI.
2.The second one is after adding the data-parsley-excluded=true attribute to your field_to_be_ignore.
$("#myForm").on('submit'), function(e) {
e.preventDefault();
var form = $(this);
//the first validation bind the error message to the screen
if (form.parsley().validate() == false) {
$('myFieldToIgnore').attr('data-parsley-excluded','true');
//Now let make a second validation:
form.parsley().validate();
}
else {
//submit
}
});

Related

Toggling between $pristine and $dirty in AngularJS

I want to detect when a user has entered values into any form field by using the $dirty property and setting a flag accordingly. Not surprisingly, this works:
$scope.$watch('formDetails.$dirty', function() {
USR.userInputRecorded = true;
});
But I'd also like to detect when/if the user has emptied all fields and effectively restored the form to its original empty state. The snippet below does not work and I'm not sure why. Is there a way to watch for when the form changes back to "not dirty"?
$scope.$watch('formDetails.$pristine', function() {
USR.userInputRecorded = false;
});
Thanks.
Try this:
$scope.$watch('formDetails.$dirty', function(value) {
if (value === '') {
// field has been emptied;
your.form.$setPristine(true);
} else {
USR.userInputRecorded = true;
}
});

Enable/disable validation for angular form with nested subforms using `ng-form`

I need to enable/disable all validation rules in Angular form or subform under ng-form="myForm" based on a scope variable $scope.isValidationRequired. So, if isValidationRequired is false, none of the validations set for the designated group of fields will run, and the result will always be myForm.$valid==true, otherwise, the validation rules will run as usual.
I did a lot of research, and realized that this feature is not available out of the box with Angular. However, I found some add-ons or with some customization, it is possible.
For example, I can use the add-on angular-conditional-validation (github and demo) with custom directive enable-validation="isValidationRequired". This will be perfect, except that I cannot apply this feature for a group of fields under ng-form. I have to add this directive for each and every field where applicable.
The other solution is to use custom validation using Angular $validators pipeline. This requires some extra effort and I don't have time since the sprint is almost over and I have to give some results in a few days.
If you have any other suggestions please post an answer.
Use Case:
To clarify the need for this, I will mention the use-case. The end user can fill the form with invalid data and he can click Save button and in this case, the validation rules shouldn't be triggered. Only when the user clicks Validate and Save then the validation rules should be fired.
Solution:
See the final plunker code here.
UPDATE: as per comments below, the solution will cause the browser to hang if inner subforms are used under ng-form. More effort is needed to debug and resolver this issuer. If only one level is used, then it works fine.
UPDATE: The plunker here was updated with a more general solution. Now the code will work with a form that has sub-forms under ng-form. The function setAllInputsDirty() checks if the object is a $$parentForm to stop recursion. Also, the changeValidity() will check if the object is a form using $addControl then it will call itself to validate its child objects. So far, this function works fine, but it needs a bit of additional optimization.
One idea is to reset the errors in the digest loop if the validation flag is disabled. You can iterate through the form errors on change and set them to valid, one by one.
$scope.$watch(function() {
$scope.changeValidity();
}, true);
$scope.changeValidity = function() {
if ($scope.isValidationRequired === "false") {
for (var error in $scope.form.$error) {
while ($scope.form.$error[error]) {
$scope.form.$error[error][0].$setValidity(error, true);
}
}
}
}
Here is a plunkr: https://plnkr.co/edit/fH4vGVPa1MwljPFknYHZ
This is the updated answer that will prevent infinite loop and infinite recursion. Also, the code depends on a known root form which can be tweaked a bit to make it more general.
References: Pixelastic blog and Larry's answer
Plunker: https://plnkr.co/edit/ycPmYDSg6da10KdoNCiM?p=preview
UPDATE: code improvements to make it work for multiple errors for each field in each subform, and loop to ensure the errors are cleared on the subform level
var app = angular.module('plunker', []);
app.controller('MainCtrl', ["$scope", function($scope) {
$scope.isValidationRequired = true;
var rootForm = "form";
function setAllInputsDirty(scope) {
angular.forEach(scope, function(value, key) {
// We skip non-form and non-inputs
if (!value || value.$dirty === undefined) {
return;
}
// Recursively applying same method on all forms included in the form except the parent form
if (value.$addControl && key !== "$$parentForm") {
return setAllInputsDirty(value);
}
if (value.$validate){
value.$validate();
}
// Setting inputs to $dirty, but re-applying its content in itself
if (value.$setViewValue) {
//debugger;
return value.$setViewValue(value.$viewValue);
}
});
}
$scope.$watch(function() {
$scope.changeValidity();
}, true);
$scope.changeValidity = function(theForm) {
debugger;
//This will check if validation is truned off, it will
// clear all validation errors
if (!theForm) {
theForm = $scope[rootForm];
}
if ($scope.isValidationRequired === "false") {
for (var error in theForm.$error) {
errTypeArr = theForm.$error[error];
angular.forEach (errTypeArr, function(value, idx) {
var theObjName = value.$name;
var theObj = value;
if (theObj.$addControl) {
//This is a subform, so call the function recursively for each of the children
var isValid=false;
while (!isValid) {
$scope.changeValidity(theObj);
isValid = theObj.$valid;
}
} else {
while (theObj.$error[error]) {
theObj.$setValidity(error, true);
}
}
})
}
} else {
setAllInputsDirty($scope);
}
}
}]);

getting form undefiend in angularjs

I am creating web app using angularjs. I have integrate the dirPaginate directive for pagination.I am paginate the forms, Pagination works fine.When I submit the form first time.Form submit Succesfully. When I click on next number on pagiantion list and submit form again it says form is undefiend.
Here is Form:
var form = amazon.form; // first time works, after paginate gives undefiend
$rootScope.amazonForm = form;
// Show error messages and exit.
if (form.$invalid) {
if (form.$pristine) {
form.$setDirty();
}
}
You can watch the form and can save the form to $scope
$scope.$watch('amazon.form', function(amazonForm) {
if(amazonForm) {
$scope.amazonForm = amazonForm;
}
});
then can use below code in your function
$scope.amazon.form = $scope.amazonForm;
var form = $scope.amazon.form;

How to validate with regular expression and display error message in xeditable

I am using xeditable in my project.
I need to validate each and every field,
how to do validation using ng-pattern="/^[a-zA-Z ]*$/" and show error message if the input value does not match the pattern.
can any one guide me how can i proceed with this.
Fiddle
$scope.checkName = function(data) {
console.log("user.name.onbeforesave:", data)
if (data !== 'awesome') {
return "Username should be `awesome`";
}
};
Do you need to use ng-pattern? Can you not change the function to use the regexp?
This works:
$scope.checkName = function(data) {
console.log("user.name.onbeforesave:", data)
if (!data.match(/^[a-zA-Z ]*$/)) {
return "Only spaces and letters allowed";
}
}

Reset form after being submitted

I know it has been asked several times and I already read the other questions but my problem still remains. I have a simple form and I want the validation to disappear after being successfully submitted.
Here is a plunker:
function FormController($scope) {
$scope.formData = {
firstname: 'Eugene',
lastname: 'Crabs',
username: 'MrCrabs'
};
$scope.submit = submit;
function submit() {
if ($scope.someForm.$invalid) {
return;
}
$scope.formData = {};
$scope.someForm.$setUntouched();
return;
}
}
http://plnkr.co/edit/cJYStvlveHvAxhlza0Q0?p=preview
It's a simple task, it can't be that hard. What am I missing?
in your case change ng-show to
(someForm.username.$dirty || submitted)
in code
<div class="error-message" ng-show="(someForm.username.$dirty || submitted)">
note: it must be submitted, NOT form.$submitted
update your function in controller
$scope.submit = function() {
// set form is submitted
$scope.submitted = true;
if ($scope.someForm.$invalid) {
return;
}
$scope.formData = {};
// set form default state
$scope.someForm.$setPristine();
// set form is no submitted
$scope.submitted = false;
return;
}
and it works
more info about solution
plukr demo
This is a very interesting topic; I believe this forked plunker does what you want: http://plnkr.co/edit/RSSFFBmJ6MZtX3aaoNLb?p=preview
The key implementation points are:
Put an enableMessages flag in the scope
When the submit button is pressed, make the flag true before validation
Change the error message display conditions as:
<span ng-show="someForm.firstname.$error.required && (someForm.firstname.$dirty || enableMessages)">Please enter your firstname</span>
It reads "display this message if the field has an error and it has been touched by the user OR messages are enabled for the entire form".
Putting such a long condition in the HTML is a bad practice, so I would consider writing a helper function, e.g. (UNTESTED CODE):
$scope.showCondition = function(fieldName, validatorName) {
return $scope.someForm[fieldName].$error[validatorName] &&
($scope.someForm[fieldName].$dirty || enableMessages);
};
The ng-show becomes much more concise:
<span ng-show="showCondition('firstname', 'required')">Please enter your firstname</span>
In this case the enableMessages is no longer a scope variable, but a private var of the controller.

Resources