angular validation - prevent button ng-click() when form is invalid - angularjs

I have an angular form as part of a single page App. The 'Continue' button moves a user to the next section of the app, and has an ng-click. I would like to prevent this ng-click from happening when the button is clicked and the form is invalid, but I don't want to disable the Continue button.
Example: A user comes to the page and immediately clicks the Continue button without providing a first name. The error message "You should provide a first name" is shown and the user remains on the page.
How can I do this? Here is the code:
<form name="form" novalidate >
<div ng-show="form.FirstName.$touched && form.FirstName.$error.required" class="errorMessage">
You must enter a first name
</div>
<div class="form-group">
<label for="firstName" class="form-label">First Name</label>
<input id="firstName" class="form-control" name="FirstName" ng-model="vm.user.firstName" required />
</div>
<div class="btn-group">
<button ng-click="vm.next()">Continue</button>
</div>
</form>

Just add form.$valid && before the function call:
<form name="form" novalidate >
<div ng-show="form.FirstName.$touched && form.FirstName.$error.required" class="errorMessage">
You must enter a first name
</div>
<div class="form-group">
<label for="firstName" class="form-label">First Name</label>
<input id="firstName" class="form-control" name="FirstName" ng-model="vm.user.firstName" required />
</div>
<div class="btn-group">
<button ng-click="form.$valid && vm.next()">Continue</button>
</div>
</form>

Either a button is disabled or it's clickable, you can't have it both ways.
What you could do in your controller for vm.next() is say:
myApp.controller('Page1Controller'), ['$scope', function ($scope)
{
$scope.vm = {};
$scope.vm.next = function()
{
if (! $scope.vm.isFormValid())
return;
//move to the next page with your current code
...
}
$scope.vm.isFormValid()
{
$scope.vm.shouldShowError = $scope.form.valid; //add vm.shouldShowError to your error message ng-show in the view so it will display only after clicking continue
return $scope.form.valid;
}
}]);

Related

AngularJS show error when submitting

I am using AngularJS step wizard and inside the form for the first step I need validation errors to appear when the use tries to hit submit. Right now I have the following:
<span class="error" ng-show="user.validate.step1.firstname.$invalid">Required Field</span>
But the error shows when I first goto the step and when I start typing in the field it goes away, I would like this to appear when the user tries to hit submit, not when they first goto the step. I already have this to indicate a required field
<span class="error">*</span>
Here is the full code:
<form name="user.validate.step1" novalidate>
<div class="container">
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label for="firstname" class="col-md-4 form-label">First Name:</label>
<div class="col-md-8">
<div class="input-group">
<input class="form-control" type="text" name="firstname" ng-model="user.firstname" value="{{user.firstname}}" ng-blur="blur1=true" required />
<span class="error" ng-show="user.validate.step1.firstname.$invalid">*</span>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
keep in mind I have more than one input in this form.
Add the validation in the button using ng-click="validateInputs()" and create a var invalidEntry and a function validateInputs() to check if the input is valid or not. Something like this:
var inputs = [inputModel1,inputModel2,inputModel3];
function validateInputs(){
invalidEntry = false;
for(e in inputs){
if(CheckInvalid(inputs[e])){
invalidEntry = true;
return;
}
}
}
function CheckValid(string){
if(string == "" || string === null || string === undefined){
return true;
} else {
return false;
}
}
The submit button:
<button ng-click="validateInputs()">Submit</button>
And the span:
<span class="error" ng-show="invalidEntry">Required Field</span>
And the inputs should look like this:
<input type="text" ng-model="inputModel1"></input>
<input type="text" ng-model="inputModel2"></input>
<input type="text" ng-model="inputModel3"></input>
You should change ngShow in following way
ng-show="user.validate.step1.firstname.$invalid && !user.validate.step1.firstname.$pristine"
Check this article block AngularJS Form Validation: Only Showing Errors After Submitting the Form

Angular js ng-model

There are two buttons, through which popup is opened,
I have input field in that popup and applied validations on that input field.
If I close the popup and clicks on second button then input value is already got filled, because I used same input field to reduce code.
How to reset that ng-model value of input field?
I tried to set it null on click of close button, but after clicking on second button it set null but shows valiation errors on first time.
How to achieve this functionality using same input field?
<form name="vm.pvtZipCodeSearchForm" id="pvtZipCodeSearchForm" class="clearfix">
<div class="alert alert-danger" ng-if="vm.errorMsg">{{vm.InvalidAddressError}}</div>
<fieldset class="form-control form-control-wrapper">
<div class="fields">
<input type="text" class="form-control" placeholder="{{vm.lang.tcZipCode}}Postnummer*" title="{{vm.lang.tcZipCode}}*" name="zipCode" maxlength="5" ng-model="vm.tariff.zipCode" ng-maxlength="5" ng-minlength="5" ng-required="!disable" />
<div ng-if="vm.isValidForm" class="error-message" ng-messages="vm.pvtZipCodeSearchForm.zipCode.$error" role="alert">
<div ng-message="required">{{vm.lang.errMsgBlankField}}</div>
<div ng-message="minlength">{{vm.lang.errMsgShortField}}</div>
<div ng-message="maxlength">{{vm.lang.errMsgLongField}}</div>
</div>
</div>
<br />
<div class="fields tac">
<button type="button" ng-click="vm.tcSearchZipCode()" class="tc___button--search">{{vm.lang.search}}</button>
</div>
</fieldset>
</form>
You can try setting
vm.pvtZipCodeSearchForm.zipCode.$pristine = true;

hide submit button again after clicking (ng-show - form validation)

I have the following code, which shows the a.btn anchor if both inputs have values and inputURL is a valid URL. Works fine but I want to hide the button again on click, how do I do this, do I reset the form or actually hide the button on click?
<form name="myForm" class="row inputs">
<div class="col-xs-5">
<label for="exampleInputPassword1">Enter a Title/Description</label>
<input name="inputName" type="text" id="urlName" class="form-control" placeholder="" ng-model="mvName" required>
</div>
<div class="col-xs-5">
<label for="exampleInputPassword1">Enter a URL</label>
<input type="url" name="inputURL" id="urlLink" class="form-control" placeholder="" ng-model="mvUrl" required>
</div>
<div class="col-xs-2">
Post
</div>
</form>
What I've done before is create a scope variable in your controller:
$scope.formSubmitted = false;
Then in your saveToList function set $scope.formSubmitted to true. From here you have a few options. If you're "Post" button is an actual button then you could set the disabled attribute. You could also check if formSubmitted is true inside your saveToList function and if it is true you don't continue. Or you can change your ng-show to be:
ng-show="myForm.$valid && !formSubmitted"
you can do something like this:
define another $scope.someToggle variable, and assign it true, then at the ng-show of the button add it like ng-show="myForm.$valid && someToggle". then at the end (or in callback) of saveToList($event) function, set $scope.someToggle to false.
also you can put this on both inputs: ng-change = "someToggle = true" so whenever they change(after the save button has been clicked) you'd be able to bring it back...
HTML
<body ng-app="myApp">
<div ng-controller="formCtrl">
<form name="myForm" class row inputs">
<div class="col-xs-5">
<label for="exampleInputPassword1">Enter a Title/Description</label>
<input name="inputName" type="text" id="urlName" class="form-control" placeholder="" ng-model="mvName" required>
</div>
<div class="col-xs-5">
<label for="exampleInputPassword1">Enter a URL</label>
<input type="url" name="inputURL" id="urlLink" class="form-control" placeholder="" ng-model="mvUrl" required>
</div>
<div class="col-xs-2">
Post
</div>
</form>
</div>
</body>
controller
var app = angular.module('myApp', []);
app.controller('formCtrl', function($scope) {
$scope.saveToList = function() {
$scope.mvName = '';
$scope.mvUrl = '';
}
});
Alternative
with scope variable without invalidating form
Post
app.controller('formCtrl', function($scope) {
$scope.logicalExp = "||";
$scope.formSubmitted = true;
$scope.saveToList = function() {
$scope.logicalExp = "&&";
$scope.formSubmitted = true;
}
});
the problem with this is, user needs to invalidate the form by himself by removing entered value then hyperlink will be hidden-ed.

validate form on button in angularjs

I have to validate a form only after click on button. Now it is working on blur and focus. How can I disable focus and blur validation and validate them on button click. fiddle
<form ng-app="form-example" class="row form-horizontal" novalidate>
<div class="control-group">
<label class="control-label" for="inputEmail">Email</label>
<div class="controls">
<input type="email" id="inputEmail" placeholder="Email" ng-model="email" required>
<div class="input-help">
<h4>Invalid Email</h4>
</div>
</div>
</div>
<div class="control-group">
<label class="control-label" for="inputPassword">Password</label>
<div class="controls">
<input ng-model="password" class="immediate-help" required type="password" id="inputPassword" placeholder="Password">
<div class="input-help">
<ul>
<li>required</strong></li>
</ul>
</div>
</div>
</div>
<div class="control-group">
<div class="controls">
<button class="btn">Create Account</button>
</div>
</div>
</form>
You could have dummy class on your form level that will tell the form has been submitted or not like ng-class="{submitted: submitted}", and on click of button we will use ng-click="submitted=true" so that after clicking on button form will have submitted class on it. Then we will apply our CSS rule for ng-invalid & ng-dirty to also consider an .submitted class by using concept of deep nesting of classes.
/* Show red border when stuff has been typed in, but its invalid */
.submitted .ng-dirty.ng-invalid {
border-color:#ec3f41;
}
Other CSS rules should be taken care of this thing like I shown above.
the problem is that you just added the validation and you're showing the message on ng-invalid ( with css). here is an example of working code to do what you want.
<div class="form-group col-xs-12 required" ng-class="{ 'has-error' : creditCardDetailsForm.security_code.$invalid && submitted}">
<label class="col-lg-28 col-l-5 col-md-5 text-left font-l-20 primary control-label">Security code (CVC) </label>
<div class="col-lg-3 col-md-4 text-left">
<input class="form-control" name="security_code" data-stripe="cvc" ng-model="payment_details.security_code" type="number" minLength="3" required>
<p ng-show="creditCardDetailsForm.security_code.$invalid && submitted" class="help-block">Security code is required.</p>
<p ng-show="creditCardDetailsForm.security_code.minLength.$invalid && submitted" class="help-block">Invalid CVC.</p>
</div>
</div>
see, here I check if the form is invalid and the submitted has been clicked...
in my controller:
$scope.purchasePackage = function (status, response) {
$scope.submitted = true;
if ($scope.creditCardForm.creditCardDetailsForm.$valid) {
//do something
}
};
since you did your hide and show with CSS you can just add the class on click to the form and then do .submitted .ng-invalid so it only shows up after you have submitted.

AngularJS and Bootstrap: Red border on invalid input field on submit

I've this basic form implemented using AngularJS and Bootstrap:
http://jsfiddle.net/dennismadsen/0stwd03k/
HTML
<div ng-controller="MyCtrl">
<form class="well" name="formTest" ng-submit="save()">
<div class="form-group">
<label for="name">Name*</label>
<input type="name" class="form-control" id="name" placeholder="Enter name" required />
</div>
<button type="submit" class="btn btn-default">Submit</button>
</form>
</div>
JavaScript
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.save = function () {
};
}
Result
The Name input field is required. When I click the submit button, I need the input field to have a red border if it's invalid. How can this be done?
Alternatively, if I unfocus the input field and it's still not valid, it would be great that the red corder is shown on that time, instead of waiting for the form submit.
Twitter Bootstrap has an has-error class, so I would use this in conjunction with ng-class for the form group, then a label with the label and label-danger classes for good measure:
<div class="form-group" ng-class="{'has-error': errors.Name }">
<label for="name">Name*</label>
<input type="name" class="form-control" id="name" placeholder="Enter name" required />
<span class="label label-danger" ng-if="errors.Name">{{errors.Name}}</span>
</div>
Then in your controller, have an errors object, and set the Name property of this to a string when the name is invalid.
The first thing you were missing was adding ng-model='name' to input field, then only will the form become invalid once you click submit, otherwise the form will always be valid since it considers that there is no field present.
Then I'd add the submitted class on the submit click button, then put the border css like .submitted would be the parent and .ng-invalid would be the child so we can put the style on .submitted .ng-invalid
HTML
<div ng-controller="MyCtrl">
<form class="well" name="formTest" ng-class="{'submitted': submitted}" ng-submit="save()" >
<div class="form-group">
<label for="name">Name*</label>
<input type="name" class="form-control" id="name" placeholder="Enter name" ng-model="name" required />
</div>{{submitted}}
<button type="submit" class="btn btn-default" ng-click="submitted= true;">Submit</button>
</form>
</div>
CSS
.submitted .ng-invalid{
border: 1px solid red;
}
Working Fiddle
Hope this could help you, Thanks.
Basically you need angular to take over validation, so add novalidate to form. Also add ng-class to input field to determine wether to add error css
<form name="myForm" novalidate ng-submit="test()">
<input type="text" name="user" ng-model="user" required ng-class="myForm.user.$invalid && myForm.user.$dirty ? 'error' : ''">
<span style="color:red" ng-show="myForm.user.$dirty && myForm.user.$invalid">
<span ng-show="myForm.user.$error.required">Username is required. </span>
</span>
<p>
<input type="submit"
ng-disabled="myForm.user.$dirty && myForm.user.$invalid ||
myForm.email.$dirty && myForm.email.$invalid">
</p>
</form>
Good luck..

Resources