<!DOCTYPE html>
<html>
<head>
<script data-require="jquery@2.0.3" data-semver="2.0.3" src="http://code.jquery.com/jquery-2.0.3.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" rel="stylesheet" data-semver="3.3.2" data-require="bootstrap@3.3.2" />
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js" data-semver="3.3.2" data-require="bootstrap@3.3.2"></script>
<script data-require="angular.js@1.4.0-rc.0" data-semver="1.4.0-rc.0" src="https://code.angularjs.org/1.4.0-rc.0/angular.js"></script>
<script src="https://rawgit.com/pocesar/angular-async-validator/master/angular-async-validator.js"></script>
<link href="style.css" rel="stylesheet" />
</head>
<body class="container" ng-controller="Main as main">
<tabs class="col-xs-12">
<tab label="'Simple'">
<div ng-include="'simple.html'"></div>
</tab>
<tab label="'Advanced'">
<div ng-include="'advanced.html'"></div>
</tab>
<tab label="'Promises'">
<div ng-include="'promises.html'"></div>
</tab>
<tab label="'Multiple'">
<div ng-include="'multiple.html'"></div>
</tab>
</tabs>
<script src="script.js"></script>
</body>
</html>
// Code goes here
angular
.module('app', ['AsyncValidator'])
.config(['AsyncValidatorProvider', function(AsyncValidatorProvider){
AsyncValidatorProvider
.register('registeredValidator', [function(){
return function(value, options, $model){
return angular.isUndefined($model.$viewValue) || $model.$viewValue.length < 5;
}
}])
.register('asyncHttp', ['$http', function($http){
return function(value, options, $model){
return $http.get('test.json').then(function(result){
return result.error;
});
};
}])
.register('setOtherValidities', [function(){
return function(value, options, $model) {
if ($model.$viewValue) {
if ($model.$viewValue.length < 4) {
$model.$setValidity(options.key, false);
return false;
}
}
$model.$setValidity(options.key, true);
return !$model.$error[options.key];
};
}])
.register('reuseValidator', [function(){
return function(value, options, $model) {
switch (options.mode) {
case 'number':
return /^[0-9]+$/.test($model.$viewValue);
case 'object':
try {
return angular.isObject(JSON.parse($model.$viewValue));
} catch (e) {
return false;
}
case 'boolean':
return !!$model.$viewValue;
}
return true; // never fail the base validator
};
}])
;
}])
.controller('Main', ['$q', '$timeout', function($q, $timeout){
this.data = {
};
this.loaded = false;
this.controllerValidator = function(model, options){
};
}])
.directive('tabs', [function(){
return {
restrict: 'E',
controllerAs: 'tabs',
templateUrl: 'tabset.html',
transclude: true,
controller: [function(){
var current = null;
this.labels = [];
this.current = function(id){
if (id) {
current = id;
}
return current;
};
this.label = function(label){
this.labels.push(label);
};
}]
};
}])
.directive('tab', [function(){
return {
restrict: 'E',
require: '^tabs',
transclude: true,
templateUrl: 'tab.html',
scope: {
label: '='
},
link: function(scope, el, attrs, ctrl){
ctrl.label(scope.label);
scope.current = function(){
return scope.label == ctrl.current();
};
}
};
}]);
angular.bootstrap(document, ['app'], {strictDi: true});
/* Styles go here */
.nav-tabs {
margin-bottom: 20px;
}
.ng-pending + .loading:after {
content: "Loading ...";
}
.ng-invalid.ng-touched {
box-shadow: 0px 0px 3px red;
}
<div ng-if="current()">
<div class="tab-pane active">
<div class="panel panel-default">
<div class="panel-heading" role="tabpanel">{{ label }}</div>
<div class="panel-body" ng-transclude></div>
</div>
</div>
</div>
<div class="row">
<div class="col-xs-12">
<ul class="nav nav-tabs" role="tablist">
<li ng-repeat="label in tabs.labels" ng-class="{'active': tabs.current() == label}">
<a href="#" ng-click="tabs.current(label)">{{ label }}</a>
</li>
</ul>
<div ng-transclude class="tab-content"></div>
</div>
</div>
<form name="main.simpleForm">
<div class="form-group">
<label>async-validator="'$value.length > 0'"</label>
<input type="text" class="form-control" async-validator="'$value.length > 0'" name="simple1" ng-model="main.data.simple1">
{{ main.simpleForm.simple1.$error }}
</div>
<div class="form-group">
<label>async-validator="'main.loaded || $value'"</label>
<input type="text" class="form-control" async-validator="'main.loaded || $value'" name="simple2" ng-model="main.data.simple2">
{{ main.simpleForm.simple2.$error }} {{ {'main.loaded': main.loaded } }} <button type="button" class="btn" ng-click="main.loaded=!main.loaded;main.simpleForm.simple2.$validate();">Toggle 'main.loaded'</button>
</div>
<div class="form-group">
<label>async-validator="'$value != main.data.simple2'"></label>
<input type="text" class="form-control" async-validator="'$value != main.data.simple2'" name="simple3" ng-model="main.data.simple3">
{{ main.simpleForm.simple3.$error }}
</div>
</form>
<form name="main.advancedForm">
<div class="form-group">
<label>async-validator="['registeredValidator','$value.length > 3']"</label>
<input type="text" async-validator="['registeredValidator','$value.length > 3']" class="form-control" name="advanced1" ng-model="main.data.advanced1">
{{ main.advancedForm.advanced1.$error }}
</div>
<div class="form-group">
<label>async-validator="{number: 'reuseValidator', object: 'reuseValidator', boolean: 'reuseValidator'}"</label>
<input type="text"
async-validator="{number: 'reuseValidator', object: 'reuseValidator', boolean: 'reuseValidator'}"
async-validator-options-number="{mode:'number'}"
async-validator-options-object="{mode:'object'}"
async-validator-options-boolean="{mode:'boolean'}"
class="form-control" name="advanced2"
ng-model="main.data.advanced2">
{{ main.advancedForm.advanced2.$error }}
</div>
</form>
<form name="main.multipleForm">
<div class="form-group">
<label>async-validator="'setOtherValidities'" async-validator-options="{ key: 'anotherValidation' }"</label>
<input type="text" name="multiple1" class="form-control" async-validator="'setOtherValidities'" async-validator-options="{ key: 'anotherValidation' }" ng-model="main.data.multiple1">
{{ main.multipleForm.multiple1.$error }}
</div>
</form>
<form name="main.promisesForm">
<div class="form-group">
<label>async-validator="'asyncHttp'"</label>
<input type="text" async-validator="'asyncHttp'" name="promises1" class="form-control" ng-model="main.data.promises1"> <i class="loading"></i>
<br>{{ main.promisesForm.promises1.$error }}
</div>
</form>
{
"error": true
}