Angular: Attach directive
http://angularjs.org/
by Oli Gustafsson
HTML
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.3/angular.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css">
<div ng-controller="MyCtrl">
<div class="col-md-12">
<table class="table table-condensed">
<thead>
<tr>
<th>Name</th>
<th>$valid</th>
<th>$invalid</th>
<th>$dirty</th>
<th>$pristine</th>
<th>$touched</th>
<th>$untouched</th>
<th>Error</th>
</tr>
</thead>
<tr ng-repeat="field in testForm">
<td>{{field.$name}}</td>
<td ng-class="{'success':field.$valid, 'danger': !field.$valid}">{{field.$valid}}</td>
<td ng-class="{'success':field.$invalid, 'danger': !field.$invalid}">{{field.$invalid}}</td>
<td ng-class="{'success':field.$dirty, 'danger': !field.$dirty}">{{field.$dirty}}</td>
<td ng-class="{'success':field.$pristine, 'danger': !field.$pristine}">{{field.$pristine}}</td>
<td ng-class="{'success':field.$touched, 'danger': !field.$touched}">{{field.$touched}}</td>
<td ng-class="{'success':field.$untouched,'danger': !field.$untouched}">{{field.$untouched}}</td>
<td style="width: 40%;">{{field.$error}}</td>
</tr>
</table>
<button class="btn btn-primary" ng-click="toggleValidate()">Toggle validation</button>
Do Validate: {{doValidate}}
<br /><br />
<form name="testForm" id="testForm">
<input
name="testInput"
type="text"
ng-class="{'error': testForm.testInput.$invalid && testForm.testInput.$dirty }"
ng-model="input"
attach-directive="{'validate-test': validateLogic() }"
/>
</form>
</div>
</div>
CSS
.error {
background: red;
}
JavaScript
var myApp = angular.module('myApp',[]);
myApp.directive('attachDirective', function($compile, $timeout) {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
scope.$watch(attrs.attachDirective, attachWatchAction, true);
function attachWatchAction(newValue) {
angular.forEach(newValue, function (value, key) {
if (value) {
if (!element.attr(key)) {
var inputVal = element.val();
element.attr(key, true);
$compile(element)(scope);
$timeout(function () {
element.val(inputVal);
scope.$apply();
}, 0);
}
} else {
if (element.attr(key)) {
element.removeAttr(key);
$compile(element)(scope);
}
}
});
}
}
};
});
myApp.directive('validateTest', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ctrl) {
ctrl.$parsers.unshift(function (value) {
var valid = value === 'test';
ctrl.$setValidity('validateTest', valid);
return valid ? value : undefined;
});
ctrl.$formatters.unshift(function (value) {
var valid = value === 'test';
ctrl.$setValidity('validateTest', valid);
return value;
});
}
}
});
myApp.controller('MyCtrl', function($scope) {
$scope.doValidate =...