我创建了一个检查URL是否确实存在的指令:
用法:
<input name="urlName" type="text" url-checker />
<span class="danger" ng-show="urlForm.urlName.$error.urlChecker">invalid url</span>
和指令代码:
(function () {
'use strict';
var directiveId = 'urlChecker';
/**
* Purpose: check whether a model's value matches a valid url
*/
angular.module('comp.directives').directive(directiveId, ['$http', directiveFunc]);
function directiveFunc($http) {
return {
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
element.bind('blur', function (e, n) {
//check url starts with http:// or https://
if (ngModel.$modelValue.indexOf('http://') === -1 || ngModel.$modelValue.indexOf('http://') === -1) {
ngModel.$setValidity('urlChecker', false);
} else {
//check the url actually exists
$http.get(ngModel.$modelValue).success(function (result) {
ngModel.$setValidity('urlChecker', true);
}).error(function (error) {
ngModel.$setValidity('urlChecker', false);
});
}
});
}
};
}
})();
我不知道如何测试它。任何帮助,将不胜感激。到目前为止,我已经这样做了:
'use strict'
describe('urlChecker', function () {
var scope, compile, element;
beforeEach(function () {
inject(function ($rootScope, $compile) {
compile = $compile;
scope = $rootScope;
})
});
it('should should set the model validity to false', function () {
scope.model = 'http://www.yahoo.fr';
element = angular.element('<input type="text" ng-model="model" url-checker />');
compile(element)(scope);
scope.$digest();
var elm = element[0];
elm.blur();
});
});
答案 0 :(得分:0)
结帐NgModelController:$parsers。您可能不应该绑定到输入'blur',因为您最终可能会与输入指令冲突。
link: function (scope, element, attrs, ngModel) {
ngModel.$parsers.push(function(value){
if (value.indexOf('http://') === -1 || value.indexOf('http://') === -1) {
ngModel.$setValidity('urlChecker', false);
} else {
//check the url actually exists
$http.get(value).success(function (result) {
ngModel.$setValidity('urlChecker', true);
}).error(function (error) {
ngModel.$setValidity('urlChecker', false);
});
}
return value;
})
}
仔细阅读。如果您的解析器返回undefined,则ngModel将不会更新您的模型。解析器必须是同步的,因此你的异步处理程序不能暂停用户的输入。虽然您有潜在的竞争条件,但您可以在回调中设置有效性。
我可能会为这个指令创建一个控制器,只需将控制器方法推送到$解析器中,但你仍然可以这样测试。
compile(element)(scope);
scope.$digest();
var ngModel = element.controller('$ngModelController');
ngModel.$setViewValue('blah');
expect(ngModel.error['urlChecker']).toBeDefined()
您还可以通过注入$httpBackend
来测试$ http调用$httpBackend.expectGET('blah').respond(500)
$httpBackend.flush()
// Now your http handler should have fired.