Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save dxacaniest/6f244618d071d6317e75a8d66f1cec7c to your computer and use it in GitHub Desktop.
Save dxacaniest/6f244618d071d6317e75a8d66f1cec7c to your computer and use it in GitHub Desktop.
Angular + Material Design Lite ( MDL ) Form Validation
<div ng-app="validationApp" ng-controller="mainController" class="layout mdl-layout mdl-js-layout mdl-layout--fixed-header">
<main class="mdl-layout__content" data-ng-view="" ng-class="render.mdlColor? render.mdlColor : 'mdl-color--grey-100'">
<div class="mdl-grid">
<div class="mdl-cell mdl-cell--12-col">
<h4>Registration Form!</h4>
<h5 ng-if="formStatus">{{formStatus}}</h5>
<form name="form" ng-submit="submit()" novalidate>
<fieldset>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="companyName" name="companyName" ng-model="data.companyName" ng-required="true" />
<label class="mdl-textfield__label" for="companyName">Company name*</label>
<span class="mdl-tooltip mdl-tooltip--validation" for="companyName" ng-show="form.companyName.$invalid && form.companyName.$touched">
<span ng-show="form.companyName.$error.required">Required.</span>
</span>
</div>
</fieldset>
<fieldset>
<ul class="list-unstyled">
<li>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="name" name="name" pattern="[A-Za-z\s]*" ng-model="data.name" ng-required="true" />
<label class="mdl-textfield__label" for="name">Full name*</label>
<span class="mdl-tooltip mdl-tooltip--validation" for="name" ng-show="form.name.$invalid && form.name.$touched">
<span ng-show="form.name.$error.required">Required.</span>
<span ng-show="form.name.$error.pattern">Invalid pattern.</span>
</span>
</div>
</li>
<li>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="email" id="email" name="email" ng-model="data.email" ng-required="true" />
<label class="mdl-textfield__label" for="email">Email*</label>
<span class="mdl-tooltip mdl-tooltip--validation" for="email" ng-show="form.email.$invalid && form.email.$touched">
<span ng-show="form.email.$error.required">Required.</span>
<span ng-show="form.email.$error.email">Invalid email.</span>
</span>
</div>
</li>
<li>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="text" id="login" name="login" pattern="^[a-zA-Z][a-zA-Z0-9-_\.]*" minlength="3" ng-model="data.login" ng-required="true" />
<label class="mdl-textfield__label" for="login">Login*</label>
<span class="mdl-tooltip mdl-tooltip--validation" for="login" ng-show="form.login.$invalid && form.login.$touched">
<span ng-show="form.login.$error.required">Required.</span>
<span ng-show="form.login.$error.pattern">Invalid pattern.</span>
<span ng-show="form.login.$error.minlength">Minimum of three characters.</span>
</span>
</div>
</li>
<li>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="password" id="password" name="password" ng-model="data.password" ng-required="true" />
<label class="mdl-textfield__label" for="password">Password*</label>
<span class="mdl-tooltip mdl-tooltip--validation" for="password" ng-show="form.password.$invalid && form.password.$touched">
<span ng-show="form.password.$error.required">Required.</span>
</span>
</div>
</li>
<li>
<div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">
<input class="mdl-textfield__input" type="password" id="confirmPassword" name="confirmPassword" ng-model="data.confirmPassword" ng-required="true" field-match="data.password" />
<label class="mdl-textfield__label" for="confirmPassword">Confirm Password*</label>
<span class="mdl-tooltip mdl-tooltip--validation" for="confirmPassword" ng-show="form.confirmPassword.$invalid && form.confirmPassword.$touched">
<span ng-show="form.confirmPassword.$error.required">Required.</span>
<span ng-show="form.confirmPassword.$error.fieldmatch">Passwords do not match.</span>
</span>
</div>
</li>
</ul>
</fieldset>
<button type="submit" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored mdl-js-ripple-effect">Register</button>
</form>
</div>
</div>
</main>
</div>
// create angular app
var validationApp = angular.module('validationApp', ['fieldMatch']);
//Field Match directive
angular.module('fieldMatch', [])
.directive('fieldMatch', ["$parse", function($parse) {
return {
require: 'ngModel',
link: function(scope, elem, attrs, ctrl) {
var me = $parse(attrs.ngModel);
var matchTo = $parse(attrs.fieldMatch);
scope.$watchGroup([me, matchTo], function(newValues, oldValues) {
ctrl.$setValidity('fieldmatch', me(scope) === matchTo(scope));
}, true);
}
}
}]);
//Run material design lite
validationApp.run(function($rootScope, $timeout) {
$rootScope.$on('$viewContentLoaded', function(event) {
$timeout(function() {
componentHandler.upgradeAllRegistered();
}, 0);
});
$rootScope.render = {
header: true,
aside: true
}
});
// create angular controller
validationApp.controller('mainController', function($scope) {
$scope.formStatus = '';
// function to submit the form after all validation has occurred
$scope.submit = function() {
// check to make sure the form is completely valid
if ($scope.form.$invalid) {
angular.forEach($scope.form.$error, function(field) {
angular.forEach(field, function(errorField) {
errorField.$setTouched();
})
});
$scope.formStatus = "Form is invalid.";
console.log("Form is invalid.");
} else {
$scope.formStatus = "Form is valid.";
console.log("Form is valid.");
console.log($scope.data);
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.4/angular.min.js"></script>
<script src="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.min.js"></script>
/*Disable MDL validation styles*/
.mdl-textfield.is-invalid .mdl-textfield__input {
border-bottom: 1px solid rgba(0, 0, 0, .12);
}
.mdl-textfield--floating-label.is-invalid .mdl-textfield__label {
color: rgba(0, 0, 0, .26);
}
.mdl-textfield--floating-label.is-focused .mdl-textfield__label,
.mdl-textfield--floating-label.is-dirty .mdl-textfield__label {
color: rgb(63, 81, 181);
}
.mdl-textfield.is-invalid .mdl-textfield__label:after {
background-color: rgb(63, 81, 181);
}
/*Validation styles based on MDL*/
.ng-invalid.ng-invalid.ng-touched {
border-color: rgb(222, 50, 38);
box-shadow: none;
}
.ng-invalid.ng-invalid.ng-touched + label {
color: rgb(222, 50, 38);
font-size: 12px;
}
.ng-invalid.ng-invalid.ng-touched + label:after {
background-color: rgb(222, 50, 38);
}
.ng-invalid.ng-invalid.ng-touched ~ .mdl-tooltip--validation {
background-color: rgb(222, 50, 38);
}
.ng-invalid.ng-invalid.ng-touched.ng-dirty:focus {
border-color: rgb(255, 193, 7);
box-shadow: none;
}
.ng-invalid.ng-invalid.ng-touched.ng-dirty:focus + label {
color: rgb(255, 193, 7);
font-size: 12px;
}
.ng-invalid.ng-invalid.ng-touched.ng-dirty:focus + label:after {
background-color: rgb(255, 193, 7);
}
.ng-invalid.ng-invalid.ng-touched.ng-dirty:focus ~ .mdl-tooltip--validation {
background-color: rgb(255, 193, 7);
}
.ng-invalid.ng-touched:not(:focus) + label::before {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
/* Preferred icon size */
display: inline-block;
width: 1em;
height: 1em;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
content: "warning";
position: absolute;
right: 0;
bottom: 20px;
}
.ng-valid.ng-touched:not(:focus) + label::before {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
/* Preferred icon size */
display: inline-block;
width: 1em;
height: 1em;
line-height: 1;
text-transform: none;
letter-spacing: normal;
word-wrap: normal;
/* Support for all WebKit browsers. */
-webkit-font-smoothing: antialiased;
/* Support for Safari and Chrome. */
text-rendering: optimizeLegibility;
/* Support for Firefox. */
-moz-osx-font-smoothing: grayscale;
/* Support for IE. */
font-feature-settings: 'liga';
content: "done";
position: absolute;
right: 0;
bottom: 20px;
}
/*Basic styles*/
.list-unstyled {
padding-left: 0;
list-style: none;
}
<link href="https://fonts.googleapis.com/css?family=Roboto:regular,bold,italic,thin,light,bolditalic,black,medium&lang=en" rel="stylesheet" />
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet" />
<link href="https://storage.googleapis.com/code.getmdl.io/1.0.4/material.indigo-pink.min.css" rel="stylesheet" />
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment