I have an AngularJS Form with 3 required fields inside (using ng-required). Without touching anything on the form and just simply pressing the 'Submit' button (ng-click="submit"), how do I trigger validation for the required fields AND prevent form submission? I've tried doing:
ng-required="form.$submitted && !firstName"
which triggers the validation, but also submits the form even though the form is technically $invalid??
I would take a look at angular-validator: https://github.com/turinggroup/angular-validator. It is quite useful and really leans out your validation code. ng-Message is nice but you end up maintaining more HTML and therefore it seems it would be more watches.
<form name="categoryForm" id="categoryForm" class="smart-form" angular-validator angular-validator-submit="save(true)" novalidate autocomplete="off">
<fieldset>
<section ng-class="{ 'has-error' : categoryForm.title.$invalid}">
<label class="label">Title</label>
<label class="input">
<input name="title" type="text" ng-model="category.title" id="title" placeholder="Title" required
validate-on="dirty" required-message="'Title is required'">
</label>
</section>
<section ng-if="isAdmin()">
<div class="row">
<section class="col col-6" >
<label class="checkbox">
<input type="checkbox" name="checkbox" ng-model="category.isGlobal">
<i></i><span>Global</span></label>
</section>
</div>
</section>
</fieldset>
<footer>
<button type="submit" class="btn btn-primary" ng-disabled="(categoryForm.$dirty && categoryForm.$invalid) || categoryForm.$pristine">
Submit
</button>
</footer>
</form>
Since you mention that you are doing validation for individual elements and don't know to check whether the entire form is valid or not. You can use the following condition to check whether the form is valid or not
$scope.yourFormName.$valid
Use the above condition to check whether the form is valid or not. The above condition will become true only when all the required validations inside the form are valid. Hope this is what you're looking for
I used the ng-submit directive as it triggers form.$submitted and validates ng-required fields properly before submitting.
For the case where you have multiple buttons, for I added an ng-click to each button and simply changed a $scope variable (e.g. $scope.pressedBtn). In the function that ng-submit points to, you could do something like:
if ($scope.pressedBtn === 'button1') {
// submit
}
else if ($scope.pressedBtn === 'button2') {
// save
}
Related
I have an angularjs form that pulls default data from scope. With the default data the form is expected to be validated and hence enable the button for submission but the reverse is the case except data is entered on the input field and this enables the button. here is the snippet
<div ng-controller="FormValidationController as frmValidationController" class="ui basic segment">
<form class="ui form" name="frmValidation" novalidate>
<div ng-class = "{'has-error':frmValidation.option1.$invalid && !frmValidation.option1.$pristine}"
class="required field">
<label>Selection</label>
<input ng-model="option" ng-minlength="3" formcontrol
name="option1" placeholder="Option" type="text"
class="ng-dirty ng-valid ng-touched" required>
<div _ngcontent-c5="" ngxerrors="option1">
<div class="input-error-message" ngxerror="validName" hidden="">
selection should be there
</div>
</div>
<p ng-show = "frmValidation.option1.$invalid && !frmValidation.option1.$pristine"
class = "input-error-message">required</p>
</div>
if the model has data, the button should be enabled on launch but this never happens and I want it to happen
<button ng-click="submit(); frmValidationController.submitForm(frmValidation.$valid)"
ng-disabled ="!frmValidation.$dirty || frmValidation.$invalid"
class="ui primary button" tabindex="0" type="submit">
Proceed
</button>
The problem is here:
ng-disabled ="!frmValidation.$dirty || frmValidation.$invalid"
Specifically:
!frmValidation.$dirty
The form is only dirty if an actually user has interacted with it. Because you're loading default data, the form is filled in correctly but the user has NOT touched or "dirtied" it.
Remove that check and it should work as expected I believe.
Say I have the following HTML...
<div class="row">
<div class="col-xs-3 align-right">
<p>Email</p>
</div>
<div class="col-xs-7">
<input type="text" class="form-control" ng-model="registrationForm.email.value"/>
<span class="error-label" ng-hide="registrationForm.email.valid"><span class="glyphicon glyphicon-remove"></span>Must be a valid email!</span>
</div>
</div>
This bit of HTML creates an email field, with an error label that is shown if the email provided is invalid. This works perfectly, and is not part of my question.
I would like to slightly alter the behavior of this label. When the user first visits the form, I don't want to display the error label unless the user has changed the value of the form input.
It seems like the $pristine and $dirty properties are the key, but I'm confused on how to go about using them. If I try to access them of properties of email.value (I.E. registrationForm.email.value.$pristine) the property seems to be undefined.
I would like to avoid enclosing these inputs in an HTML form. Is there still a way I can retain use of these properties, and if so, how?
When you create your <form> element, it will create a $scope variable with the name of your form. For example:
<form name="regForm">
<div class="row">
<div class="col-xs-3 align-right">
<p>Email</p>
</div>
<div class="col-xs-7">
<input type="text" class="form-control" name="email" ng-model="registrationForm.email.value"/>
<span class="error-label" ng-hide="registrationForm.email.valid"><span class="glyphicon glyphicon-remove"></span>Must be a valid email!</span>
</div>
</div>
</form>
You can access the $pristine using $scope.regForm.email.$pristine.
Without a <form>, simply use ng-form, which will give you the functionality of the form, without needing an actual <form> element. See this post for more information.
I am using ngTagsInput Angular plugin for getting multiple email ids. Below is my code:
<form name="contact_us" role="form" novalidate enctype="multipart/form-data">
<div class="form-group">
<label class="control-label" for="from_email">
From
</label>
<tags-input ng-model="contactUs.emails" type="email" id="from_email"
placeholder="From" name="from_email"
allowed-tags-pattern="^[A-Za-z0-9._%+-]+#(?:[A-Za-z0-9-]+.)+[A-Za-z]{2,}"
allow-leftover-text="false" ng-required="true" add-on-space="true">
</tags-input>
<p class="help-block" style="color:red"
ng-show="contact_us.from_email.$invalid && (contact_us.$submitted || contact_us.$dirty)">
Please enter proper email address
</p>
<button type="submit" class="btn btn-default" ng-click="Send(contact_us)">
Send
</button>
</form>
In above code 3 validation has been added those are as follows:
For Mandatory fields.
Field should accept only an email id.
It should not allow duplicate email id.
The above cases are working fine. But, I want to show the error message dynamically according to the above one of the case has occurred. Please help me out !!!
ngTagsInput supports attribute below for change to capture, it fires before adding to model
on-tag-adding="foo($tag)"
$scope.foo(function(tag){
// look for error
// if found return false
// change the text of tag
tag.text='what ever';
return tag;
})
For required:
<p class="help-block" style="color:red"
ng-show="contact_us.from_email.$error.required">
email address is required
</p>
For pattern & duplicate, I think no validation flag has been provided and you have to write your own to perform validation.
For duplicate, maybe this will help.
Angularjs - How to check for unique inputs and if there is a duplicate mark both as invalid
Given this code, it never works and always returns true whatsoever ?
<form id="my-form" data-validate="parsley">
<p>
<label for="username">Username * :</label>
<input type="text" id="username" name="username" data-required="true" >
</p>
<p>
<label for="email">Email Address * :</label>
<input type="text" id="email" name="email" data-required="true" >
</p>
<br/>
<!-- Validate all the form fields by clicking this button -->
<a class="btn btn-danger" id="validate" >Validate All</a>
</form>
<script>
var $form = $('#my-form');
$('#validate').click (function () {
if ( $form.parsley('validate') )
console.log ( 'valid' ); <-- always goes here
else
console.log ('invalid');
});
</script>
So my question is if there is a way to trigger parsley validation without adding a submit button ?
$form.parsley('validate') is 1.x API. It was deprecated in 2.x versions you might use.
Try $form.parsley().validate() instead.
Best
I've been searching high and low to try and make the form validation work with a non-form tag.
I guess my biggest gripe with the framework is that it doesn't work out-of-the-box with non-form elements.
I would be ok using a form element if it didn't scroll to the top of the page every time it tries to validate. Because this behavior is inherent in how form works, there is only this hack to fix it.
Just as a side note, using data-parsley-validate attribute on the div tag also works. You can also initialise the form as normal (meaning you can subscribe to the validation).
example html:
<div id="signupForm" data-parsley-validate>
... put form inputs here ...
<button id="signupBtn">Sign me up</button>
</div>
Just make sure to put js in:
var $selector = $('#signupForm'),
form = $selector.parsley();
form.subscribe('parsley:form:success', function (e) {
...
});
$selector.find('button').click(function () {
form.validate();
});
if you put type="button" on the button, it won't refresh and scroll to top of page when clicked.
Given this code:
<div ng-controller="MyCtrl">
<form ng-submit="onSubmitted()">
Header inputs:
<input type="name" ng-model="sample" required/>
<input type="name" ng-model="sampleX" required/>
<input type="submit" value="This submit triggers validation. But I wanted to put this button at the end of the page"/>
</form>
<hr/>
Some other form here. Think line items
<hr />
<a class="btn" ng-click="/* what could should be put here, so this can trigger the firt form's validation, then submit? */">Wanted this submit button to trigger the validation+submit on the form in which this button doesn't belong</a>
</div>
var app = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.onSubmitted = function() {
alert('submitted!');
};
}
I want the last button to trigger the validation(then submit when things are valid) on first form. As of now, only the button inside the form can trigger that form's validation and submission. Is there any possible way for a button outside the form to do that?
Live test: http://jsfiddle.net/dzjV4/1/
You can create directive which you can then attach to <a class="btn".... Check this jsfiddle
http://jsfiddle.net/dzjV4/2/
Note that I added to <input type='submit' id='clickMe'... and linked it with link at the bottom <a class='btn' linked="clickMe"...
for (control of $scope.[form name].$$controls) {
control.$setDirty();
control.$validate();
}
You can try the above codes. Make it running before submit.
Ideally there'd be a programmatic way to cause validation to re-run across a form. I have not investigated that completely but had a situation that required multiple controls to be re-validated based on different data in the scope -- without the user interacting with the individual controls. This arose because the form had two action buttons which each required different validation rules be in play when they were clicked.
The UI requirement changed before I fully implemented forcing re-validation but before it did I got most of what I needed by copying and then re-setting the form's data. This forced re-validation across the form within the current scope. Basically, it's along the lines of the following (not tested, but taken from the code that was working). In this case the form's data was bound to the properties in one object.
var formData = $parse(<form's model>);
var dataCopy = angular.copy( formData($scope) );
formData.assign( $scope, dataCopy );
This may or may not be acceptable, but if you can get away with the SUBMIT button being disabled until the form is completed, you can do this:
<form name="formName">
<input ng-required="true" />
</form>
<button ng-click="someFunction()" ng-disabled="formName.$invalid" />
It's also worth noting that this works in IE9 (if you're worried about that).
Give your form a name:
<div ng-controller="MyCtrl">
<form name="myForm">
<input name="myInput" />
</form>
</div>
So you can access your form validation status on your scope.
app.controller('MyCtrl', function($scope) {
$scope.myForm.$valid // form valid or not
$scope.myForm.myInput // input valid or not
// do something with myForm, e.g. display a message manually
})
angular doc
There is no way to trigger browser form behavior outside of a form. You have to do this manually.
Since my form fields only show validation messages if a field is invalid, and has been touched by the user:
<!-- form field -->
<div class="form-group" ng-class="{ 'has-error': rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched && rfi.rfiForm.stepTwo.Parent_Suffix__c.$invalid }">
<!-- field label -->
<label class="control-label">Suffix</label>
<!-- end field label -->
<!-- field input -->
<select name="Parent_Suffix__c" class="form-control"
ng-options="item.value as item.label for item in rfi.contact.Parent_Suffixes"
ng-model="rfi.contact.Parent_Suffix__c" />
<!-- end field input -->
<!-- field help -->
<span class="help-block" ng-messages="rfi.rfiForm.stepTwo.Parent_Suffix__c.$error" ng-show="rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched">
<span ng-message="required">this field is required</span>
</span>
<!-- end field help -->
</div>
<!-- end form field -->
I was able to use this code triggered by a button to show my invalid fields:
// Show/trigger any validation errors for this step
angular.forEach(vm.rfiForm.stepTwo.$error, function(error) {
angular.forEach(error, function(field) {
field.$setTouched();
});
});
// Prevent user from going to next step if current step is invalid
if (!vm.rfiForm.stepTwo.$valid) {
isValid = false;
}