angular-async-validator
Advanced tools
Comparing version 0.2.2 to 1.0.0
declare module AsyncValidator { | ||
interface IValidationFn { | ||
(value: string | angular.INgModelController, options?: any): boolean | angular.IPromise<any>; | ||
(value: string | angular.INgModelController, options?: any, model?: angular.INgModelController): boolean | angular.IPromise<any>; | ||
} | ||
@@ -15,3 +15,2 @@ type IValidateFactory = Function | Array<string | Function>; | ||
interface IOptions { | ||
valueFrom?: boolean | string; | ||
options?: any; | ||
@@ -25,3 +24,3 @@ overwrite?: boolean; | ||
class AsyncValidator { | ||
run: <T>(name: string, value: T, options?: any, returnValue?: boolean) => angular.IPromise<T>; | ||
run: <T>(name: string, value: T, options?: any, model?: angular.INgModelController, returnValue?: boolean) => angular.IPromise<T>; | ||
options: (name: string) => IOptions; | ||
@@ -28,0 +27,0 @@ validator: (name: string) => IValidationFn; |
@@ -12,3 +12,3 @@ var AsyncValidator; | ||
}); | ||
this.run = function (name, value, options, returnValue) { | ||
this.run = function (name, value, options, model, returnValue) { | ||
if (typeof provider.validations[name] === 'undefined' || typeof provider.validations[name].validator !== 'function') { | ||
@@ -19,3 +19,3 @@ return $q.reject("" + name + " isn't a registered async validator"); | ||
return new $q(function asyncValidatorRunResolver(resolve) { | ||
resolve(provider.validations[name].validator(value, options)); | ||
resolve(provider.validations[name].validator(value, options, model)); | ||
}).then(function asyncValidatorResolved(result) { | ||
@@ -67,3 +67,2 @@ if (!!result) { | ||
this.defaultOptions = { | ||
valueFrom: false, | ||
options: {}, | ||
@@ -103,2 +102,3 @@ overwrite: true, | ||
this.$pending = []; | ||
this.$excluded = []; | ||
} | ||
@@ -115,3 +115,28 @@ AsyncForm.prototype.setup = function (callback) { | ||
}; | ||
AsyncForm.prototype.clean = function () { | ||
this.$pending.length = 0; | ||
this.callback = null; | ||
this.$excluded.length = 0; | ||
}; | ||
AsyncForm.prototype.exclude = function (model, check) { | ||
check = typeof check === 'undefined' ? false : check; | ||
var expected = false, position = -1; | ||
angular.forEach(this.$excluded, function (_model, _pos) { | ||
if (model === _model) { | ||
expected = true; | ||
position = _pos; | ||
} | ||
}); | ||
if (expected === false && check === false) { | ||
return this.$excluded.push(model); | ||
} | ||
else if (position > -1 && check === false) { | ||
this.$excluded.splice(position, 1); | ||
} | ||
return expected; | ||
}; | ||
AsyncForm.prototype.add = function (model, scope, attrs) { | ||
if (this.exclude(model, true)) { | ||
return; | ||
} | ||
if (!this.callback) { | ||
@@ -137,22 +162,24 @@ this.$pending.push({ | ||
var opts = { '__': {} }, evaled; | ||
angular.forEach(attrs.$attr, function (value, key) { | ||
if (!attrs[key]) { | ||
return; | ||
} | ||
var matches; | ||
if ((matches = value.match(optionsRegex))) { | ||
if (matches[1]) { | ||
if (angular.isObject(evaled = scope.$eval(attrs[key]))) { | ||
if (typeof opts[matches[1]] !== 'object') { | ||
opts[matches[1]] = {}; | ||
angular.forEach(attrs, function (attr) { | ||
angular.forEach(attr.$attr, function (value, key) { | ||
if (!attr[key]) { | ||
return; | ||
} | ||
var matches; | ||
if ((matches = value.match(optionsRegex))) { | ||
if (matches[1]) { | ||
if (angular.isObject(evaled = scope.$eval(attr[key]))) { | ||
if (typeof opts[matches[1]] !== 'object') { | ||
opts[matches[1]] = {}; | ||
} | ||
angular.extend(opts[matches[1]], evaled); | ||
} | ||
angular.extend(opts[matches[1]], evaled); | ||
} | ||
} | ||
else { | ||
if (angular.isObject(evaled = scope.$eval(attrs[key]))) { | ||
angular.extend(opts['__'], evaled); | ||
else { | ||
if (angular.isObject(evaled = scope.$eval(attr[key]))) { | ||
angular.extend(opts['__'], evaled); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
@@ -175,3 +202,3 @@ return opts; | ||
angular.forEach(validateExpr, function (exprssn, key) { | ||
var opts = AsyncValidator.options(key), validator = key; | ||
var opts = AsyncValidator.options(key), validator = key, alias = false; | ||
if (angular.isString(exprssn) && angular.equals(opts, {})) { | ||
@@ -181,2 +208,3 @@ opts = AsyncValidator.options(exprssn); | ||
validator = exprssn; | ||
alias = key; | ||
exprssn = '__VALIDATOR__'; | ||
@@ -194,3 +222,6 @@ } | ||
ctrl.$asyncValidators[key] = function validationFn(val) { | ||
var value, _options = parseOptions(scope, $attrs), modelOptions = _options['__']; | ||
var _options = parseOptions(scope, $attrs), modelOptions = angular.extend({}, _options['__']); | ||
if (angular.isString(alias) && typeof _options[alias] === 'object') { | ||
angular.extend(modelOptions, _options[alias]); | ||
} | ||
if (typeof _options[key] === 'object') { | ||
@@ -202,19 +233,4 @@ angular.extend(modelOptions, _options[key]); | ||
} | ||
if (opts && opts.valueFrom === false) { | ||
value = ctrl; | ||
} | ||
else if (angular.isString(opts.valueFrom)) { | ||
var model = ctrl; | ||
if (typeof model[opts.valueFrom] !== 'undefined') { | ||
value = model[opts.valueFrom]; | ||
} | ||
else { | ||
value = val; | ||
} | ||
} | ||
else { | ||
value = val; | ||
} | ||
if (exprssn === '__VALIDATOR__' || exprssn === validator) { | ||
return AsyncValidator.run(validator, value, modelOptions, false); | ||
return AsyncValidator.run(validator, val, modelOptions, ctrl, false); | ||
} | ||
@@ -252,7 +268,7 @@ else { | ||
this.link = function (scope, el, attrs, ctrls) { | ||
var validateExpr = scope.$eval(attrs['asyncFormValidator']), asyncValidatorCtrl = ctrls[1]; | ||
var validateExpr = scope.$eval(attrs['asyncFormValidator']), ngModel = ctrls[0], asyncValidatorCtrl = ctrls[1]; | ||
asyncValidatorCtrl.setup(function (model, _scope, $attrs) { | ||
addValidators(validateExpr, AsyncValidator, model, _scope, $q, $attrs); | ||
addValidators(validateExpr, AsyncValidator, model, _scope, $q, [attrs, $attrs]); | ||
}); | ||
angular.forEach(ctrls[0], function (model, key) { | ||
angular.forEach(ngModel, function (model, key) { | ||
if (angular.isObject(model) && key.charAt(0) !== '$') { | ||
@@ -263,4 +279,3 @@ asyncValidatorCtrl.add(model, scope, attrs); | ||
scope.$on('$destroy', function () { | ||
asyncValidatorCtrl.$pending.length = 0; | ||
asyncValidatorCtrl.callback = null; | ||
asyncValidatorCtrl.clean(); | ||
}); | ||
@@ -276,10 +291,38 @@ }; | ||
Directives.asyncFormValidator = AsyncFormValidator.instance(); | ||
var AsyncGroupValidator = (function () { | ||
function AsyncGroupValidator(AsyncValidator, $q) { | ||
this.restrict = 'AE'; | ||
this.require = ['asyncGroupValidator', '?^asyncFormValidator']; | ||
this.controller = Controllers.AsyncForm; | ||
this.link = function (scope, el, attrs, ctrls) { | ||
var validateExpr = scope.$eval(attrs['asyncGroupValidator']); | ||
ctrls[0].setup(function (model, _scope, $attrs) { | ||
if (ctrls[1]) { | ||
ctrls[1].exclude(model); | ||
} | ||
addValidators(validateExpr, AsyncValidator, model, _scope, $q, [attrs, $attrs]); | ||
}); | ||
scope.$on('$destroy', function () { | ||
ctrls[0].clean(); | ||
}); | ||
}; | ||
} | ||
AsyncGroupValidator.instance = function () { | ||
var _this = this; | ||
return ['AsyncValidator', '$q', function (AsyncValidator, $q) { return new _this(AsyncValidator, $q); }]; | ||
}; | ||
return AsyncGroupValidator; | ||
})(); | ||
Directives.asyncGroupValidator = AsyncGroupValidator.instance(); | ||
var AsyncValidatorAdd = (function () { | ||
function AsyncValidatorAdd() { | ||
this.restrict = 'A'; | ||
this.require = ['ngModel', '^asyncFormValidator']; | ||
this.require = ['ngModel', '?^asyncGroupValidator', '?^asyncFormValidator']; | ||
this.priority = 10; | ||
} | ||
AsyncValidatorAdd.prototype.link = function (scope, el, attrs, ctrls) { | ||
var ngModel = ctrls[0], asyncValidatorCtrl = ctrls[1]; | ||
var ngModel = ctrls[0], asyncValidatorCtrl = ctrls[1] || ctrls[2]; | ||
if (!asyncValidatorCtrl) { | ||
return; | ||
} | ||
asyncValidatorCtrl.add(ngModel, scope, attrs); | ||
@@ -294,2 +337,32 @@ }; | ||
Directives.asyncValidatorAdd = AsyncValidatorAdd.instance(); | ||
var AsyncValidatorExclude = (function () { | ||
function AsyncValidatorExclude() { | ||
this.restrict = 'A'; | ||
this.priority = 20; | ||
this.require = ['ngModel', '?^asyncGroupValidator', '?^asyncFormValidator']; | ||
} | ||
AsyncValidatorExclude.prototype.link = function (scope, el, attrs, ctrls) { | ||
var ngModel = ctrls[0], formValidatorCtrl = ctrls[2], groupValidatorCtrl = ctrls[1]; | ||
if (formValidatorCtrl) { | ||
formValidatorCtrl.exclude(ngModel); | ||
} | ||
if (groupValidatorCtrl) { | ||
groupValidatorCtrl.exclude(ngModel); | ||
} | ||
scope.$on('$destroy', function () { | ||
if (formValidatorCtrl) { | ||
formValidatorCtrl.exclude(ngModel); | ||
} | ||
if (groupValidatorCtrl) { | ||
groupValidatorCtrl.exclude(ngModel); | ||
} | ||
}); | ||
}; | ||
AsyncValidatorExclude.instance = function () { | ||
var _this = this; | ||
return [function () { return new _this; }]; | ||
}; | ||
return AsyncValidatorExclude; | ||
})(); | ||
Directives.asyncValidatorExclude = AsyncValidatorExclude.instance(); | ||
var AsyncValidator = (function () { | ||
@@ -304,3 +377,3 @@ function AsyncValidator(AsyncValidator, $q) { | ||
} | ||
addValidators(validateExpr, AsyncValidator, ctrl, scope, $q, attrs); | ||
addValidators(validateExpr, AsyncValidator, ctrl, scope, $q, [attrs]); | ||
var watches = []; | ||
@@ -307,0 +380,0 @@ function watchValues(watch) { |
@@ -13,3 +13,3 @@ (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.AsyncValidator = f()}})(function(){var define,module,exports;module={exports:(exports={})}; | ||
}); | ||
this.run = function (name, value, options, returnValue) { | ||
this.run = function (name, value, options, model, returnValue) { | ||
if (typeof provider.validations[name] === 'undefined' || typeof provider.validations[name].validator !== 'function') { | ||
@@ -20,3 +20,3 @@ return $q.reject("" + name + " isn't a registered async validator"); | ||
return new $q(function asyncValidatorRunResolver(resolve) { | ||
resolve(provider.validations[name].validator(value, options)); | ||
resolve(provider.validations[name].validator(value, options, model)); | ||
}).then(function asyncValidatorResolved(result) { | ||
@@ -68,3 +68,2 @@ if (!!result) { | ||
this.defaultOptions = { | ||
valueFrom: false, | ||
options: {}, | ||
@@ -104,2 +103,3 @@ overwrite: true, | ||
this.$pending = []; | ||
this.$excluded = []; | ||
} | ||
@@ -116,3 +116,28 @@ AsyncForm.prototype.setup = function (callback) { | ||
}; | ||
AsyncForm.prototype.clean = function () { | ||
this.$pending.length = 0; | ||
this.callback = null; | ||
this.$excluded.length = 0; | ||
}; | ||
AsyncForm.prototype.exclude = function (model, check) { | ||
check = typeof check === 'undefined' ? false : check; | ||
var expected = false, position = -1; | ||
angular.forEach(this.$excluded, function (_model, _pos) { | ||
if (model === _model) { | ||
expected = true; | ||
position = _pos; | ||
} | ||
}); | ||
if (expected === false && check === false) { | ||
return this.$excluded.push(model); | ||
} | ||
else if (position > -1 && check === false) { | ||
this.$excluded.splice(position, 1); | ||
} | ||
return expected; | ||
}; | ||
AsyncForm.prototype.add = function (model, scope, attrs) { | ||
if (this.exclude(model, true)) { | ||
return; | ||
} | ||
if (!this.callback) { | ||
@@ -138,22 +163,24 @@ this.$pending.push({ | ||
var opts = { '__': {} }, evaled; | ||
angular.forEach(attrs.$attr, function (value, key) { | ||
if (!attrs[key]) { | ||
return; | ||
} | ||
var matches; | ||
if ((matches = value.match(optionsRegex))) { | ||
if (matches[1]) { | ||
if (angular.isObject(evaled = scope.$eval(attrs[key]))) { | ||
if (typeof opts[matches[1]] !== 'object') { | ||
opts[matches[1]] = {}; | ||
angular.forEach(attrs, function (attr) { | ||
angular.forEach(attr.$attr, function (value, key) { | ||
if (!attr[key]) { | ||
return; | ||
} | ||
var matches; | ||
if ((matches = value.match(optionsRegex))) { | ||
if (matches[1]) { | ||
if (angular.isObject(evaled = scope.$eval(attr[key]))) { | ||
if (typeof opts[matches[1]] !== 'object') { | ||
opts[matches[1]] = {}; | ||
} | ||
angular.extend(opts[matches[1]], evaled); | ||
} | ||
angular.extend(opts[matches[1]], evaled); | ||
} | ||
} | ||
else { | ||
if (angular.isObject(evaled = scope.$eval(attrs[key]))) { | ||
angular.extend(opts['__'], evaled); | ||
else { | ||
if (angular.isObject(evaled = scope.$eval(attr[key]))) { | ||
angular.extend(opts['__'], evaled); | ||
} | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
@@ -176,3 +203,3 @@ return opts; | ||
angular.forEach(validateExpr, function (exprssn, key) { | ||
var opts = AsyncValidator.options(key), validator = key; | ||
var opts = AsyncValidator.options(key), validator = key, alias = false; | ||
if (angular.isString(exprssn) && angular.equals(opts, {})) { | ||
@@ -182,2 +209,3 @@ opts = AsyncValidator.options(exprssn); | ||
validator = exprssn; | ||
alias = key; | ||
exprssn = '__VALIDATOR__'; | ||
@@ -195,3 +223,6 @@ } | ||
ctrl.$asyncValidators[key] = function validationFn(val) { | ||
var value, _options = parseOptions(scope, $attrs), modelOptions = _options['__']; | ||
var _options = parseOptions(scope, $attrs), modelOptions = angular.extend({}, _options['__']); | ||
if (angular.isString(alias) && typeof _options[alias] === 'object') { | ||
angular.extend(modelOptions, _options[alias]); | ||
} | ||
if (typeof _options[key] === 'object') { | ||
@@ -203,19 +234,4 @@ angular.extend(modelOptions, _options[key]); | ||
} | ||
if (opts && opts.valueFrom === false) { | ||
value = ctrl; | ||
} | ||
else if (angular.isString(opts.valueFrom)) { | ||
var model = ctrl; | ||
if (typeof model[opts.valueFrom] !== 'undefined') { | ||
value = model[opts.valueFrom]; | ||
} | ||
else { | ||
value = val; | ||
} | ||
} | ||
else { | ||
value = val; | ||
} | ||
if (exprssn === '__VALIDATOR__' || exprssn === validator) { | ||
return AsyncValidator.run(validator, value, modelOptions, false); | ||
return AsyncValidator.run(validator, val, modelOptions, ctrl, false); | ||
} | ||
@@ -253,7 +269,7 @@ else { | ||
this.link = function (scope, el, attrs, ctrls) { | ||
var validateExpr = scope.$eval(attrs['asyncFormValidator']), asyncValidatorCtrl = ctrls[1]; | ||
var validateExpr = scope.$eval(attrs['asyncFormValidator']), ngModel = ctrls[0], asyncValidatorCtrl = ctrls[1]; | ||
asyncValidatorCtrl.setup(function (model, _scope, $attrs) { | ||
addValidators(validateExpr, AsyncValidator, model, _scope, $q, $attrs); | ||
addValidators(validateExpr, AsyncValidator, model, _scope, $q, [attrs, $attrs]); | ||
}); | ||
angular.forEach(ctrls[0], function (model, key) { | ||
angular.forEach(ngModel, function (model, key) { | ||
if (angular.isObject(model) && key.charAt(0) !== '$') { | ||
@@ -264,4 +280,3 @@ asyncValidatorCtrl.add(model, scope, attrs); | ||
scope.$on('$destroy', function () { | ||
asyncValidatorCtrl.$pending.length = 0; | ||
asyncValidatorCtrl.callback = null; | ||
asyncValidatorCtrl.clean(); | ||
}); | ||
@@ -277,10 +292,38 @@ }; | ||
Directives.asyncFormValidator = AsyncFormValidator.instance(); | ||
var AsyncGroupValidator = (function () { | ||
function AsyncGroupValidator(AsyncValidator, $q) { | ||
this.restrict = 'AE'; | ||
this.require = ['asyncGroupValidator', '?^asyncFormValidator']; | ||
this.controller = Controllers.AsyncForm; | ||
this.link = function (scope, el, attrs, ctrls) { | ||
var validateExpr = scope.$eval(attrs['asyncGroupValidator']); | ||
ctrls[0].setup(function (model, _scope, $attrs) { | ||
if (ctrls[1]) { | ||
ctrls[1].exclude(model); | ||
} | ||
addValidators(validateExpr, AsyncValidator, model, _scope, $q, [attrs, $attrs]); | ||
}); | ||
scope.$on('$destroy', function () { | ||
ctrls[0].clean(); | ||
}); | ||
}; | ||
} | ||
AsyncGroupValidator.instance = function () { | ||
var _this = this; | ||
return ['AsyncValidator', '$q', function (AsyncValidator, $q) { return new _this(AsyncValidator, $q); }]; | ||
}; | ||
return AsyncGroupValidator; | ||
})(); | ||
Directives.asyncGroupValidator = AsyncGroupValidator.instance(); | ||
var AsyncValidatorAdd = (function () { | ||
function AsyncValidatorAdd() { | ||
this.restrict = 'A'; | ||
this.require = ['ngModel', '^asyncFormValidator']; | ||
this.require = ['ngModel', '?^asyncGroupValidator', '?^asyncFormValidator']; | ||
this.priority = 10; | ||
} | ||
AsyncValidatorAdd.prototype.link = function (scope, el, attrs, ctrls) { | ||
var ngModel = ctrls[0], asyncValidatorCtrl = ctrls[1]; | ||
var ngModel = ctrls[0], asyncValidatorCtrl = ctrls[1] || ctrls[2]; | ||
if (!asyncValidatorCtrl) { | ||
return; | ||
} | ||
asyncValidatorCtrl.add(ngModel, scope, attrs); | ||
@@ -295,2 +338,32 @@ }; | ||
Directives.asyncValidatorAdd = AsyncValidatorAdd.instance(); | ||
var AsyncValidatorExclude = (function () { | ||
function AsyncValidatorExclude() { | ||
this.restrict = 'A'; | ||
this.priority = 20; | ||
this.require = ['ngModel', '?^asyncGroupValidator', '?^asyncFormValidator']; | ||
} | ||
AsyncValidatorExclude.prototype.link = function (scope, el, attrs, ctrls) { | ||
var ngModel = ctrls[0], formValidatorCtrl = ctrls[2], groupValidatorCtrl = ctrls[1]; | ||
if (formValidatorCtrl) { | ||
formValidatorCtrl.exclude(ngModel); | ||
} | ||
if (groupValidatorCtrl) { | ||
groupValidatorCtrl.exclude(ngModel); | ||
} | ||
scope.$on('$destroy', function () { | ||
if (formValidatorCtrl) { | ||
formValidatorCtrl.exclude(ngModel); | ||
} | ||
if (groupValidatorCtrl) { | ||
groupValidatorCtrl.exclude(ngModel); | ||
} | ||
}); | ||
}; | ||
AsyncValidatorExclude.instance = function () { | ||
var _this = this; | ||
return [function () { return new _this; }]; | ||
}; | ||
return AsyncValidatorExclude; | ||
})(); | ||
Directives.asyncValidatorExclude = AsyncValidatorExclude.instance(); | ||
var AsyncValidator = (function () { | ||
@@ -305,3 +378,3 @@ function AsyncValidator(AsyncValidator, $q) { | ||
} | ||
addValidators(validateExpr, AsyncValidator, ctrl, scope, $q, attrs); | ||
addValidators(validateExpr, AsyncValidator, ctrl, scope, $q, [attrs]); | ||
var watches = []; | ||
@@ -308,0 +381,0 @@ function watchValues(watch) { |
{ | ||
"name": "angular-async-validator", | ||
"version": "0.2.2", | ||
"description": "This module enables you to register your own validation rules, or overwrite existing ones. Makes every validation 'promise based', so it can deal with both synchronous and asynchronous validations. Also, sometimes you want validate an entire form when a model changes, which currently there are no good ways to do this, hence this module, because validation and form manipulation in Angular 1.x is a pain by itself.", | ||
"version": "1.0.0", | ||
"description": "Makes Angular models async validation a little less painful.", | ||
"main": "index.js", | ||
@@ -6,0 +6,0 @@ "scripts": { |
@@ -58,7 +58,8 @@ [![Build Status](https://travis-ci.org/pocesar/angular-async-validator.svg?branch=master)](https://travis-ci.org/pocesar/angular-async-validator) [![Coverage Status](https://coveralls.io/repos/pocesar/angular-async-validator/badge.svg)](https://coveralls.io/r/pocesar/angular-async-validator) | ||
.register('required', [function(){ | ||
return function(value, options){ | ||
return function(value, options, model){ | ||
// options === {} | ||
// model.$viewValue / model.$error etc | ||
return angular.isDefined(value); | ||
}; | ||
}], { valueFrom: '$$rawModelValue' }) // pluck it out from ngModel, using $$rawModelValue instead of $modelValue, because $modelValue might only be defined after required validation is actually called | ||
}]) // pluck it out from ngModel, using $$rawModelValue instead of $modelValue, because $modelValue might only be defined after required validation is actually called | ||
@@ -79,3 +80,3 @@ | ||
}; | ||
}], { valueFrom: '$viewValue', options: { someExtraOptions: true} }) | ||
}], { options: { someExtraOptions: true} }) | ||
@@ -240,2 +241,23 @@ register('equals', function(){ | ||
<!-- value will have to pass Angular internal required and our registered dummy validator --> | ||
<div async-group-validator="{ required: 'notrequired' }" async-validator-options="{ ok: true }"> | ||
<input | ||
type="tel" | ||
ng-model"ctrl.data.street" | ||
async-validator-add | ||
> | ||
<input | ||
type="text" | ||
ng-model"ctrl.data.number" | ||
async-validator-add | ||
> | ||
<input | ||
type="text" | ||
ng-model"ctrl.data.complement" | ||
async-validator-exclude | ||
> | ||
</div> | ||
</form> | ||
@@ -248,4 +270,2 @@ ``` | ||
* `valueFrom` where to get the current value. Defaults to `false`, and passes the whole ngModelController to the validator function as the first parameter. You can set to model properties like `$viewValue`, `$modelValue`, `$$lastCommittedViewValue`, `$$rawModelValue`, etc | ||
* `options` any options that the validator function receives as the second parameter, defaults to `{}` | ||
@@ -252,0 +272,0 @@ |
@@ -336,18 +336,2 @@ describe('AsyncValidator', function () { | ||
it('can recover from bad valueFrom', function(){ | ||
var invalidSpy = sinon.stub().returns(true);; | ||
Provider.register('invalidFrom', function(){ | ||
return invalidSpy; | ||
}, { valueFrom: 'nope' }); | ||
var | ||
el = input('<input ng-model="data.n2" async-validator="\'invalidFrom\'" />'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
expect(invalidSpy.args[0][0]).to.be.equal($scope.data.n2); | ||
}); | ||
it('can handle rejections inside scope functions', function(){ | ||
@@ -474,2 +458,14 @@ var invalidSpy = sinon.stub().returns($q.reject(new Error('uhoh'))); | ||
var el = input('<input ng-model="data.n5" async-validator-add>'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
var el = input('<div async-group-validator="{ dummy: \'ok()\' }"><input ng-model="data.n5" async-validator-add></div>'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
expect(el.el.find('input').controller('ngModel')).to.have.deep.property('$$success.dummy', true); | ||
$scope.$destroy(); | ||
@@ -480,2 +476,29 @@ }); | ||
describe('async-group-validator', function(){ | ||
it('works like async-form-validator but for any element', function(){ | ||
var el = input('<div async-group-validator><input ng-model="data.n6" async-validator-add></div>'); | ||
}); | ||
it('takes precedence over async-form-validator', function(){ | ||
var spy = sinon.stub().returns(false); | ||
Provider.register('gimme', function(){ | ||
return spy; | ||
}); | ||
var el = input('<form async-form-validator="\'gimme\'" async-validator-options="{ options: true }"><div async-group-validator="{ heh: \'gimme\' }" async-validator-options="{ options: false }"><input ng-model="data.n6" name="n6" async-validator-add></div></form>'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
var inputModel = el.el.find('input').controller('ngModel'); | ||
expect(inputModel).to.have.deep.property('$error.heh', true); | ||
expect(inputModel).to.not.have.deep.property('$error.gimme'); | ||
expect(inputModel).to.have.deep.property('$modelValue', undefined); | ||
expect(spy.args[0][0]).to.equal($scope.data.n6); | ||
expect(spy.args[0][1]).to.deep.equal({ options: false }); | ||
}); | ||
}); | ||
describe('async-validator-options', function(){ | ||
@@ -487,7 +510,7 @@ | ||
Provider.register('dummy', function(){ | ||
return function(value, options){ | ||
return function(value, options, model){ | ||
spy({value: value, options: options}); | ||
return true; | ||
}; | ||
}, { valueFrom: '$modelValue' }); | ||
}); | ||
@@ -498,3 +521,3 @@ var el = input('<input ng-model="data.n2" async-validator="{notdummy:\'dummy\'}" async-validator-options="{to: data.n3}">'); | ||
expect(spy.getCall(0).args[0]).to.deep.equal({value: $scope.data.n2, options: { to: $scope.data.n3 } }); | ||
expect(spy.args[0][0]).to.deep.equal({value: $scope.data.n2, options: { to: $scope.data.n3 } }); | ||
expect(el.controller()).to.have.deep.property('$$success.notdummy', true); | ||
@@ -515,3 +538,3 @@ | ||
return spy; | ||
}, { valueFrom: '$viewValue' }); | ||
}); | ||
@@ -522,3 +545,3 @@ var el = input('<input ng-model="data.n2" async-validator="{notdummy:\'dummy\'}" async-validator-options="{to: 1}" async-validator-options-notdummy="{to: 2}" async-validator-options-dummy="{to: 3}">'); | ||
expect(spy.args[0]).to.be.deep.equal([$scope.data.n2, { to: 3 }]); | ||
expect(spy.args[0]).to.be.deep.equal([$scope.data.n2, { to: 3 }, el.controller()]); | ||
}); | ||
@@ -530,3 +553,3 @@ | ||
return spy; | ||
}, { valueFrom: '$viewValue' }); | ||
}); | ||
@@ -537,13 +560,15 @@ var el = input('<input ng-model="data.n2" async-validator="{notdummy:\'dummy\'}" async-validator-options="{one: 1}" async-validator-options-notdummy="{two: 2}" async-validator-options-dummy="{three: 3}">'); | ||
expect(spy.args[0]).to.be.deep.equal([$scope.data.n2, { one: 1, two: 2, three: 3 }]); | ||
expect(spy.args[0]).to.be.deep.equal([$scope.data.n2, { one: 1, two: 2, three: 3 }, el.controller()]); | ||
}); | ||
it('should merge all available options that applies', function(){ | ||
var spy = sinon.stub().returns(true); | ||
var | ||
dummies = sinon.stub().returns(true), | ||
fines = sinon.stub().returns(true); | ||
Provider.register('dummy', function(){ | ||
return spy; | ||
}, { valueFrom: '$viewValue' }); | ||
return dummies; | ||
}); | ||
Provider.register('fine', function(){ | ||
return spy; | ||
}, { valueFrom: '$viewValue' }); | ||
return fines; | ||
}); | ||
@@ -554,3 +579,23 @@ var el = input('<input ng-model="data.n2" async-validator="{notdummy:\'dummy\', ok: \'fine\'}" async-validator-options="{one: 1}" async-validator-options-nope="{two: 2}" async-validator-options-dummy="{three: 3}">'); | ||
expect(spy.args[0]).to.be.deep.equal([$scope.data.n2, { one: 1, three: 3 }]); | ||
expect(dummies.args[0]).to.be.deep.equal([$scope.data.n2, { one: 1, three: 3 }, el.controller()]); | ||
expect(fines.args[0]).to.be.deep.equal([$scope.data.n2, { one: 1 }, el.controller()]); | ||
expect(el.controller()).to.be.have.deep.property('$$success.notdummy', true); | ||
expect(el.controller()).to.have.deep.property('$$success.ok', true); | ||
dummies.reset(); | ||
fines.reset(); | ||
el = input('<div async-group-validator="\'fine\'" async-validator-options="{four: 4}" async-validator-options-dummy="{five: 5}"><input async-validator-add ng-model="data.n2" name="hohoho" async-validator="{notdummy:\'dummy\', ok: \'fine\'}" async-validator-options="{one: 1}" async-validator-options-nope="{two: 2}" async-validator-options-dummy="{three: 3}"></div>'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
expect(fines.args[0][1]).to.be.deep.equal({ one: 1 }); | ||
expect(fines.args[1][1]).to.be.deep.equal({ one: 1, four: 4 }); | ||
expect(dummies.args[0][1]).to.be.deep.equal({ one: 1, three: 3 }); | ||
var inputModel = el.el.find('input').controller('ngModel'); | ||
expect(inputModel).to.have.deep.property('$$success.fine', true); | ||
expect(inputModel).to.have.deep.property('$$success.notdummy', true); | ||
expect(inputModel).to.have.deep.property('$$success.ok', true); | ||
}); | ||
@@ -578,11 +623,11 @@ | ||
Provider.register('reuseValidator', function(){ | ||
return function($model, options) { | ||
spy($model.$viewValue, options.mode); | ||
return function(value, options, model) { | ||
spy(value, options.mode); | ||
switch (options.mode) { | ||
case 'number': | ||
return /^[0-9]+$/.test($model.$viewValue); | ||
return /^[0-9]+$/.test(value); | ||
case 'object': | ||
try { | ||
return angular.isObject(JSON.parse($model.$viewValue)); | ||
return angular.isObject(JSON.parse(value)); | ||
} catch (e) { | ||
@@ -592,3 +637,3 @@ return false; | ||
case 'boolean': | ||
return !!$model.$viewValue; | ||
return !!value; | ||
} | ||
@@ -632,3 +677,29 @@ return true; // never fail the base validator | ||
it('can exclude models from validations', function(){ | ||
Provider.register('test', function(){ | ||
return sinon.stub().returns(false); | ||
}); | ||
var el = input('<form async-form-validator="\'test\'"><input async-validator-exclude name="n6" ng-model="data.n6"></form>'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
expect(el.controller('form')).to.not.have.deep.property('$error.test'); | ||
el = input('<div async-group-validator="\'test\'"><input async-validator-exclude name="n6" ng-model="data.n6"></div>'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
expect(el.el.find('input').controller('ngModel')).to.not.have.deep.property('$error.test'); | ||
el = input('<form async-form-validator="\'test\'"><input name="n6" ng-model="data.n6"><input async-validator-exclude name="n7" ng-model="data.n7"></form>'); | ||
el.compiled($scope); | ||
$scope.$digest(); | ||
expect(el.controller('form').n6).to.have.deep.property('$error.test', true); | ||
expect(el.controller('form').n7).to.not.have.deep.property('$error.test'); | ||
$scope.$destroy(); | ||
}); | ||
}); | ||
@@ -635,0 +706,0 @@ }); |
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
84936
1555
0
278