In this code lab we will try different methods of form validations in AngularJs
.
bower
to install the angular dependency
angular
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}$/i
ng-message
We 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-message
Sometimes 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