In this code lab we will try different methods of form validations in AngularJs.
bower to install the angular dependencyangular dependency</body> tag, for performance reasons.The application looks pretty bad and for sure by now some of you started to improve it :)
bower to install and save the bootstrap-css dependencybootstrap.css and bootstrap-theme.css files inside the head tagng-app directive to the top element in the page[[_twoWayBinding('1 + 1')]] will do)index.html in a browser and check the result. If you got back what you entered as an expression AngularJs is not bootstraped. Try again!formValidationApp modulesrc inside the project folderapp.module.js inside a newly created folder
(function(){
angular.module("formValidationApp", []);
}());ng-app directiveapp.module.js fileindex.html and the result should be the samebody to have a clean slate.FormValidationCtrl controllerapp.controller.js inside a newly created folder
(function (module) {
var FormValidationCtrl = function () {
var vm = this;
};
module.controller("FormValidationCtrl", FormValidationCtrl);
}(angular.module("formValidationApp")));ng-controller directive to the body tag and set its value to the controller's name. (use the as syntax).app.controller.js fileThe form will have the following fields:
The fields have the following rules
All fields are requiredName field has a minimum of 5 characters and a maximum of 20Amount is a number (only integer amounts, without . or ,)Email is, well, an emailPlace the following HTML snippet inside the body tag
<div class="page-header">
<h1>Form Validation</h1>
</div>
<form name="sendMoney" class="form-horizontal">
<div class="form-group">
<label for="name" class="col-sm-2 control-label">Friend's name:</label>
<div class="col-sm-9">
<input class="form-control"
type="input"
id="name"
name="name"
ng-model="vm.model.name"/>
</div>
</div>
<!-- TODO the rest of the fields -->
<div class="form-group">
<div class="col-sm-offset-2 col-sm-9">
<!-- print errors -->
<pre>sendMoney.name.$error = [[_twoWayBinding('sendMoney.name.$error | json')]]</pre>
<!-- TODO print errors for every field from the form -->
</div>
</div>
</form>
see <input>)see input directive)bower to install the angular-messages dependencyindex.html file (right after angular)
(function(){
angular.module("formValidationApp", ["ngMessages"]);
}());
ng-messages directiveRight after the name input tag add
<div ng-messages="sendMoney.name.$error" class="help-block">
<div ng-message="required">This field is required</div>
<div ng-message="minlength">The field is too short</div>
<div ng-message="maxlength">The field is too long</div>
</div>
Add the following to the form-group that contains the name input tag
ng-class="{'has-error': sendMoney.name.$invalid}"Add validation messages and styling for all the other fields
Hint not all the fields require all messages and some fields may require an extra message
The validation messages should appear only when we touch the field or when we submit the form
form-group that prints the error messages with the following
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default">Confirm</button>
</div>
</div>
novalidate attribute to the form element to disable default browser validationng-class expressions to (adapt for each field)
ng-class="{'has-error': (sendMoney.$submitted || sendMoney.name.$touched) && sendMoney.name.$invalid}"
ng-messages directive accordingly (again, adapt for each field)
ng-messages="(sendMoney.$submitted || sendMoney.name.$touched) && sendMoney.name.$error"
There is no default validation implemented in AngularJs for an IBAN structure, so we need to validate it in a custom way.
ng-pattern attribute directive and use this regular expression as value /^RO[0-9]{2}[a-z]{4}[0-9a-z]{16}$/ing-messageWe only want to send to our friend maximum 100 RON
We can still use the ng-pattern directive to validate this but we can also create our own directive to validate that a number is less than a specified limit.
Create a new file maxAmount.directive.js inside the src folder
(function (module) {
var link = function (scope, element, attrs, ngModelCtrl) {
ngModelCtrl.$validators.maxAmount = function(value) {
// TODO make validation here - return true if the value from the field is less than the limit set in maxAmount param
};
};
var MaxAmount = function () {
return {
restrict: 'A',
require: 'ngModel',
scope: {
maxAmount: '=maxAmount'
},
link: link
};
};
module.directive("maxAmount", MaxAmount);
}(angular.module("formValidationApp")));
TODO above with the correct expressionmaxAmount directive to the Amount field with the correct valueng-messageSometimes a validation needs some data from the backend; for example, if we want to be sure that the IBAN really exists, we could get the valid IBANs from the backend and check if the one introduced by the user is on the list of valid IBANs.
{
"John Smith": "RO56INGB2345678435672345",
"Peter Smith": "RO56INGB2345678435672346"
}
directive, ibanValidator.directive.js in src folder
(function (module) {
var ibanValidator = function ($q, $http) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModelCtrl) {
ngModelCtrl.$asyncValidators.ibanValidator = function (value) {
return $http.get('data/validIbans.json').then(function successCallback(response) {
var ibans = Object.keys(response.data).map(function (user) {
return response.data[user];
});
if (ibans.indexOf(value) === -1) {
return $q.reject();
}
return $q.resolve();
});
};
}
};
};
module.directive("ibanValidator", ibanValidator);
}(angular.module("formValidationApp")));
Make sure an invalid error message is shown when the IBAN entered is not part of the valid-ibans list