parsley js - conditional required if checkbox checked - parsley.js

Is there an easy way with parsleyjs to make a field required depending on another field?
See my js fiddle here http://jsfiddle.net/marksteggles/wbhLq0t4/1/
<form data-parsley-validate="true">
<div class="form-group">
<label>
<input name="request_signature" type="checkbox" />Require signature</label>
<div class="request_signature_fields">
<textarea class="form-control required" name="signature_reason" rows="3"></textarea>
</div>
</div>
<input class="btn btn-success" name="commit" type="submit" value="Send" />
</form>

Minimally as of 2.2.0 you can create a custom validator:
window.Parsley.addValidator("requiredIf", {
validateString : function(value, requirement) {
if (jQuery(requirement).val()){
return !!value;
}
return true;
},
priority: 33
})
This gets applied in such a way:
<textarea
class="form-control required"
name="signature_reason"
rows="3"
data-parsley-validate-if-empty="true"
data-parsley-required-if="#my-field-to-check"
></textarea>
Explanation
data-parsley-required-if is the custom validator we just defined. It takes any arbitrary jQuery selector and if that field contains a non-falsy value it ensures that this field is not empty.
data-parsley-validate-if-empty is needed to ensure that the field is being validated at all, because Parsley does not validate empty non-required fields by default.
More data on custom validators here: http://parsleyjs.org/doc/index.html#custom

There is no easy way yet (see this and this).
You can either toggle the attribute required with Javascript, or listen to the right parsley events on one field and check the other field.

Just incase anyone else is trying to work this out. The best way does seem to be altering the required attribute then clearing the values.
I used this:
HTML:
<input id="checkbox-id" type="checkbox">
<div id="conditional-inputs" style="display:none;">
<input type="text" name="somename" />
<input type="text" name="othername" />
<input type="text" name="onemoreforluck" />
</div>
jQuery:
$("#checkbox-id").change(function() {
if(this.checked) {
$('#conditional-inputs').slideDown();
/* use .slideDown to display conditional input block */
$("#conditional-inputs :input").prop('required', true);
/* set required attribute on all inputs inside conditional area */
}
else{
$('#conditional-inputs').slideUp();
/* use .slideUp to hide conditional input block */
$("#conditional-inputs :input").prop('required', false).val('');
/* remove required attribute on all inputs and empty values of inputs */
}
})

I realise that this question was asked and answered in 2012, and is most likely related to the ParsleyJS v1, while the most recent version at the time of writing this is v2.2.0. However I had to do some work on an old form that used v1 and I found that conditionals are possible (with a little bit of jQuery). So here's to anyone who might still need this.
You can dynamically add and remove form elements and constraints (read: validation rules) using the following:
$('#form').parsley('addItem', '#input_id');
$('#form').parsley('removeItem', '#input_id');
$('#input_id').parsley('addConstraint', '{ required: true }');
$('#input_id').parsley('removeConstraint', 'required');
So using jQuery listeneners for when the checkbox changes we can execute this kind of code which will add the signature field as a required field. Here it is in action for the question.
< script src = "js/parsley-v1.js" > < /script>
<script>
$('#request_signature').on('click', function() {
if($(this).is(':selected')) {
$('#signature_form').parsley('addItem', '#signature_reason');
$('#signature_reason').parsley('addConstraint', { required: true });
} else {
$('#signature_reason').parsley('removeConstraint', 'required' });
$('#signature_form').parsley('removeItem', '#signature_reason');
}
});
</script >
<form id="signature_form" data-parsley-validate="true">
<div class="form-group">
<label>
<input id="request_signature" name="request_signature" type="checkbox" />Require signature</label>
<div class="request_signature_fields">
<textarea id="signature_reason" class="form-control" name="signature_reason" rows="3"></textarea>
</div>
</div>
<input class="btn btn-success" name="commit" type="submit" value="Send" />
</form>

You can also hide the parts that are not required anymore, or disable the fields that are not needed, and add [disabled] and :hidden to the excluded Parsley option.
{
excluded: 'input[type=button], input[type=submit], input[type=reset], input[type=hidden], [disabled], :hidden',
}
NB: you don't need to hide each field, hiding a parent div is enough.
I found a good example that I forked here
➡️ http://jsfiddle.net/capripot/xoaLs4bt/

This should be possible with the great little Parsley addon plugin found here: http://themonk.github.io/parsely-conditions/

I found the shortest method -
$('input[type=radio][name=nlcsu]').change(function() {
// I am checking for a Radio button
if (this.value == 1) {
$("#nlcsu_post").attr('required', '1');
$("#nlcsu_year").attr('required', '1');
} else if (this.value == 0) {
$("#nlcsu_post").removeAttr('required');
$("#nlcsu_year").removeAttr('required');
}
});

Related

AngularJS - perform extra validation on form submit

I've been googling for a while and can't seem to find a good answer for my specific case. I've found ways to do real-time validations but I want to combine that with some custom validations after a user clicks on "submit". I want to allow the user to still click on the submit even if it's not valid but then I'll cancel the submission in the code. Take the following code:
<form name="cashForm" id="cashForm" novalidate>
<input type="text" id="name" required /> //
<input type="number" placeholder="Tax: " required name="tax" id="tax" />
<input type="number" placeholder="Tip: " required name="tip" id="tip" />
<button ng-click="submission()" ng-disabled="paymentForm.$invalid">Submit</button>
</form>
//inside controller
this.submission = function() {
//check if tip + tax is over 20
//prevent form and show error message if not
//otherwise allow default behavior
}
So I only want the form to actually submit if the tax/tip is over 10. How do I check for this and how do I prevent the form submission if it doesn't meet the requirements? Also, would I put this logic in the controller?
It looks pretty close to what you're after to me. Just a couple of things...
Add ng-model directives to your input controls to create two-way data-bindings that you can pick up and use in your controller:
<form name="cashForm" id="cashForm" novalidate>
<input id="name" name="name" type="text" ng-model="nameValue" required />
<input id="tax" name="tax" type="number" ng-model="taxValue" placeholder="Tax: " required />
<input id="tip" name="tip" type="number" ng-model="tipValue" placeholder="Tip: " required />
<button
ng-click="submission()"
ng-disabled="paymentForm.$invalid">
Submit
</button>
Inject $scope into your controller to allow you to pick up those ng-model bindings in your controller's submission method:
function submission() {
$scope.errorMsg = "";
if ($scope.taxValue <= 10) {
$scope.errorMsg = "tax not greater than 10";
return;
}
if ($scope.tipValue <= 10) {
$scope.errorMsg = "tip not greater than 10";
return;
}
// If you reached here your post-click validation passed,
// so continue to submit the data...
}
You could then display an error message using the ng-if directive with a css class that highlights the error message:
<div ng-if="!!errorMessage" class="text-danger">
{{ errorMessage }}
</div>
Finally, once you've cracked using $scope in your controller you might want to read about the perceived evils of using $scope and consider switching to controller-as syntax instead. Check out John Papa's Blog Post AngularJS's Controller As and the vm Variable

Angular: Disable button on click after required fields are filled in the form

I need to disable the submit button after clicking on the button to prevent multiple submissions but before the it has to ensure that the required fields are filled.
I tried
<body ng-app="ngToggle">
<div ng-controller="AppCtrl">
<form name="newUserForm">
<input type="text" required>
<input type="text" required>
<input type="text">
<button ng-click="disableClick()" ng-disabled="isDisabled"
ng-model="isDisabled">Disable ng-click</button>
</form>
</div>
</body>
angular.module('ngToggle', [])
.controller('AppCtrl',['$scope', function($scope){
$scope.isDisabled = false;
$scope.disableClick = function() {
alert("Clicked!");
$scope.isDisabled = true;
return false;
}
}]);
but this will only disable the button without any validation
Ok, I get what you mean/want so I'll try to help and come up with some code - which is obviously missing but if it wasn't missing the necessary code, you'd have the solution :)
First, you'll have to properly write your form:
<form name="newUserForm" ng-submit="disableClick(newUserForm.$valid)" novalidate>
<input type="text" name="input1" ng-model="form.input1" required>
<input type="text" name="input2" ng-model="form.input2" required>
<input type="text" name="input3" ng-model="form.input3"> //not required
<button type="submit" ng-disabled="isDisabled">Disable ng-click</button>
</form>
so what we've got here, which you're missing:
You did name your form, but you're missing a submit, in the form as ng-submit or the button with type="submit", which will submit the form and that's when the validation happens
In order for Angular to validate your inputs, they need to have ng-model, otherwise it will not validate (HTML5 validation would, but read on)
I've added novalidate so we tell the browser "Hey, we need this validated but not by you, so do nothing", and Angular takes over
And last but not least, Angular adds a couple of properties to the form (see more here: Angular form Docs), $valid being one of them, which is set to true when all validated inputs are valid.
So this sums up the changes you needed to do to your form.
As for the Javascript part, there is just one small change:
$scope.disableClick = function(valid) {
if(valid && !$scope.isDisabled) {
$scope.isDisabled = true;
}
return false;
}
I guess the change is obvious, but I'll explain anyway - check that newUserForm.$valid (boolean) and if it's true (meaning form has passed validation) disable this button.
Of course, you'll have to add checks not to run the code on any type of submits and not just disabling the button (which can easily be re-enabled via Dev Tools), so that's why I added !$scope.isDisabled to the if statement.
Hope this answers your question :)
P.S. Here's a running demo in Plunker

In Angular 2, ngIF is not working when i am trying with two way binding

I am working with Angular2 with two way binding concept [(ngModel)].I have form with my page and I have to validate the pristine state of the element. So for validation I have used ngIf to check the pristine state of the element. But the condition is not working. I need to check the pristine state for every model change. Below is my app.component.html page:
<form (ngSubmit)="angular2form(myAngular2Form.employeeDob)" [ngFormModel]="myAngular2Form">
<input type="text" class="form-control" id="employee" name="employee" [(ngModel)]="employeeDob" required />
<div *ngIf="employeeDob.pristine">
<p>Please enter the date</p>
</div>
<button type="submit" class="btn btn-primary">Register</button>
</form>
This is my component:
export class AppComponent {
employeeDob: String;
constructor(private myform: FormBuilder) {
this.employeeDob = '';
}
angular2form(date) {
alert("date submitted successfully");
}
}
Thanks for any suggestion
<input type="text" class="form-control" id="employee" name="employee" [(ngModel)]="employeeDob" #date="ngModel" required />
<div [hidden]="date.valid || date.pristine">
<p>Please enter the date</p>
</div>
straight outta documentation
https://angular.io/docs/ts/latest/guide/forms.html
pristine is a property of the Control not of the value.
You might want to use
<input #employeeDobCtrl="ngForm" type="text" class="form-control" id="employee" name="employee" [(ngModel)]="employeeDob" required />
<div *ngIf="employeeDobCtrl.pristine">
(for the old forms module)
pristine is true if the user has not interacted with the form yet. You probably want to check for dirty instead? You can also use the hidden tag and replace
<div *ngIf="employeeDob.pristine">
with:
<div [hidden]="employeeDob.pristine">

Error message does not hide after angular form validation

This is my form my HTML
<form id = "myform" name="myform" ng-submit="saveForm()" novalidate >
<div class="input-group">
<span class="input-group-addon"> <img src="/icon.png" alt=""/> </span>
<input type="text" class="form-control" id="username" name="username" ng-model="username" placeholder="Username" autofocus required>
</div>
<span ng-show="formInvalid">Please enter username</span>
<button type="submit" class="btn btn-default" id="saveBtn"> Save </button>
</form>
And inside the controller I have
$scope.formInvalid = false;
$scope.saveForm = function(){
if($scope.myform.username.$invalid){
$scope.formInvalid = true;
}
if($scope.myform.$valid){
//....save it....
At first the form has no error message, if I hit "Save" the "Please enter username" appears, so far, all good.
But if I click on the form field to type a username, the error message does not go away. Even if I finish typing and click somewhere else, the error message still does not go away.
I also try
if(!$scope.myform.username.$valid){
$scope.formInvalid = true;
}
and I also try together
if(!$scope.myform.username.$valid){
$scope.formInvalid = true;
}
if($scope.myform.username.$valid){
$scope.formInvalid = false;
}
and the problem is still there. How can I debug? How do I fix this?
Thanks
You don't have to introduce and maintain a new variable ($scope.formInvalid) for managing the state of your form. Angular maintains the valid / invalid state of the form for you.
As your form is named myform, just show the message about the username based on the value of myform.username.$invalid, and save the form only if myform.$valid is true:
HTML
<span ng-show="myform.username.$invalid">Please enter username</span>
JS
$scope.saveForm = function () {
if ($scope.myform.$valid) {
// save the form
}
};
See fiddle
you can try a watch event,
$scope.$watch('myform.$valid', function(n, o) {
if(n) {
$scope.formInvalid = false;
} else {
$scope.formInvalid = true;
}
});
But i might even be a better idea, if you start using validators.
you do not trigger a change to form invalid property anywhere, I suggest you solve this issue with angulars built in validators and ng-messages module, which will listen to changes on you're form inputs and notify when the inputs are valid or invalid and notify the warning text.
Another approach you can take is use the ng-change directive on the inputs you want to listen to changes in and trigger and update on the form invalid property according to the inputs validity.
example : (taken from the official angular website )
<form name="myForm">
<label>
Enter your name:
<input type="text"
name="myName"
ng-model="name"
ng-minlength="5"
ng-maxlength="20"
required />
</label>
<pre>myForm.myName.$error = {{ myForm.myName.$error | json }}</pre>
<div ng-messages="myForm.myName.$error" style="color:maroon" role="alert">
<div ng-message="required">You did not enter a field</div>
<div ng-message="minlength">Your field is too short</div>
<div ng-message="maxlength">Your field is too long</div>
</div>
</form>
i think this is the most elegant way to do it.

Translated form validation in AngularJS

What's the easiest way of changing the default error messages in form validation provided by Angular to another language?
If I'm not mistaken, you think about html5 validation.
Something like this:
<b>HTML5 validation</b>
<form>
First name:
<input type="text" name="firstName" required="" />
<br />
Last name:
<input type="text" name="lastName" required="" />
<br />
<input type="submit" value="Submit" />
</form>
If user click on the Submit button he will see:
I think that this error comment you cannot change because it depends on the user browser/computer settings.
Maybe you should try to use angularjs validation (first add to form novalidate to switch off HTML5 validation):
HTML
<div ng-controller="PersonController">
<b>AngularJS validation</b>
<form novalidate name="myForm">
First name:
<input type="text" name="firstName" ng-model="newPerson.firstName" required="" />
<span style="color: red" ng-show="myForm.firstName.$dirty && myForm.firstName.$invalid">First name is required</span>
<br />
Last name:
<input type="text" name="lastName" ng-model="newPerson.lastName" required="" />
<span style="color: red" ng-show="myForm.lastName.$dirty && myForm.lastName.$invalid">Last name is required</span>
<br />
<button ng-click="resetPerson()">Reset</button>
<button ng-click="addPerson()" ng-disabled="myForm.$invalid">Save</button>
</form>
</div>
JavaScript
var myApp = angular.module('myApp', []);
myApp.controller('PersonController', ['$scope',
function($scope) {
var emptyPerson = {
firstName: null,
lastName: null
};
$scope.addPerson = function() {
alert('New person added ' + $scope.newPerson.firstName + ' ' + $scope.newPerson.lastName);
$scope.resetAdvert();
};
$scope.resetPerson = function() {
$scope.newPerson = angular.copy(emptyPerson);
// I don't know why not work in plunker
//$scope.myForm.$setPristine();
};
$scope.resetPerson();
}
]);
If user fill the field and erase he will see the error info:
The submit button will be disabled if user don't fill the required fields.
Plunker example
Why don't you try something easy for a change... :) Well here is my Angular-Validation. I made a project on Github and I think you can't be simpler than that...and yes I also support translation localization, those are saved into an external JSON file:
<!-- example 1 -->
<label for="input1">Simle Integer</label>
<input type="text" name="input1" validation="integer|required" ng-model="form1.input1" />
<span class="validation text-danger"></span>
<!-- example 2 -->
<label for="input2">Alphanumeric + Exact(3) + required</label>
<input type="text" name="input2" validation="alpha|exact_len:3|required" ng-model="form1.input2" />
<span class="validation text-danger"></span>
JSON external file for translation locales
// English version, JSON file (en.json)
{
"INVALID_ALPHA": "May only contain letters. ",
"INVALID_ALPHA_SPACE": "May only contain letters and spaces. ",
...
}
// French version, JSON file (fr.json)
{
"INVALID_ALPHA": "Ne doit contenir que des lettres. ",
"INVALID_ALPHA_SPACE": "Ne doit contenir que des lettres et espaces. ",
...
}
On top of supporting multiple translations, the directive is so crazy simple for validation, that you'll just love it. I can define whatever amount of validation rules (already 25+ type of validators available) under 1 attribute. validation="min_len:2|max_len:10|required|integer" and the error message will always be displayed in the following <span> isn't it beautiful? I think so too hehe... 1 line of code for your input, 1 line of code for the error display, can you beat that? oh and I even support your custom Regex if you want to add. Another bonus, I also support whichever trigger event you want, most common are probably onblur and onkeyup. I really added all the imaginable features I wanted into 1 crazy simple directive.
No more clustered Form with 10 lines of code for 1 input (sorry but always found that ridiculous) when the only little piece you need is 2 lines of code, nothing more, even for an input of 5 validators on it. And no worries about the form not becoming invalid, I took care of that as well, it's all handled the good "Angular" way.
Take a look at my Github project Angular-Validation... I'm sure you'll love it =)
DEMO
Added a live demo on Plunker

Resources