Angularjs 如何正确验证自定义指令的属性?

Angularjs 如何正确验证自定义指令的属性?,angularjs,validation,angular-directive,Angularjs,Validation,Angular Directive,假设我有这样一个自定义指令: 验证foo和bar属性是否有效的正确方法是什么?我的意思是,它们是指令工作所必需的,我不是说类型验证。我需要的是验证该属性是否存在,因为它对于该特定属性是必需的(不确定是否应该检查它是否未定义,这可能属于类型验证) 是否有任何内置的方法来实现这一点,或者我必须自己在链接中实现这一点功能?一个更好的问题可能是,这样做有意义吗?或者我应该保证我的应用程序正在使用单元测试将值传递给指令的特定控制器吗?但是当属性值是静态的并且不来自控制器的作用域时会发生什么呢 想法?不,

假设我有这样一个自定义指令:

验证
foo
bar
属性是否有效的正确方法是什么?我的意思是,它们是指令工作所必需的,我不是说类型验证。我需要的是验证该属性是否存在,因为它对于该特定属性是必需的(不确定是否应该检查它是否未定义,这可能属于类型验证)

是否有任何内置的方法来实现这一点,或者我必须自己在
链接中实现这一点
功能?一个更好的问题可能是,这样做有意义吗?或者我应该保证我的应用程序正在使用单元测试将值传递给指令的特定控制器吗?但是当属性值是静态的并且不来自控制器的作用域时会发生什么呢


想法?

不,属性没有任何内置验证。你必须自己做。一种更简洁的方法是,当其中一个必需属性的值在not valid上未定义时抛出异常

另一种方法是在未找到所需数据的情况下简单返回,因为引发异常可能会导致其他问题


也不要假设你的控制器或应用程序总是在属性中传递有效的数据,这样你就可以添加这些检查,使你的代码具有防弹性。

< P>如果你只需要确保属性不是可选的,它是指范围内的有效变量,那么再考虑(如果你不理会这个想法)将这些属性与隔离作用域的
=
一起使用

因此,您可以使用以下命令指定所需的范围变量:

scope: { requiredVar: '=requiredAttribute' },
scopeRequired: [ 'requiredVar' ],
link
是修改行为的好地方,因为它涉及范围,并且(如果它嵌套在
compile
中)它可以从中获得对
this.scopeRequired
的引用

当然,您可以按指令执行此操作,但如果您希望将其作为全球行为。。。这是我用来分解指令的配方

app.config(['$injector', function ($injector) { var _get = $injector.get; $injector.get = function patchedGet() { var provider = _get.apply(this, arguments); var providerName = arguments[0]; var directiveName = (providerName.match(/(.+)DirectiveProvider$/) || [])[1]; if (directiveName) { var _$get = provider.$get; console.log(['hi from injector get', arguments[0], provider.$get]); provider.$get = function patched$Get() { var instances = _$get.apply(this, arguments); console.log(['hi from provider $get', providerName, instances]); angular.forEach(instances, function(instance) { function getPatchedPostlink (postlink) { return function patchedPostlink(scope, element, attrs, ctrls) { var _postlink = postlink; console.log(['hi from directive link', directiveName, scope, element, attrs, ctrls]); // here it goes if (scope.$$isolateBindings && instance.scopeRequired) { var bindings = scope.$$isolateBindings; angular.forEach(instance.scopeRequired, function (scopeVar) { if (!bindings[scopeVar] || !attrs.hasOwnProperty(bindings[scopeVar].attrName)) { throw new Error("Scope variable '" + scopeVar + "', required by directive '" + directiveName + "', wasn't assigned!"); } }); } return angular.isFunction(_postlink) ? _postlink.apply(this, arguments) : undefined; }; } var _compile = instance.compile; // 'link' is impotent if there is 'compile' if (_compile) { instance.compile = function patchedCompile(element, attrs) { var compile = _compile.apply(instance, arguments); console.log(['hi from directive compile', directiveName, this, element, attrs]); if (!compile) { compile = {}; } else if (angular.isFunction(compile)) { compile = { post: compile }; } // compile.pre = getPatchedPrelink(compile.pre); compile.post = getPatchedPostlink(compile.post); return compile; }; } else { instance.link = getPatchedPostlink(instance.link); } }, this); return instances; }; } return provider; }; }]); app.config(['$injector',函数($injector){ var_get=$injector.get; $injector.get=函数patchedGet(){ var provider=\u get.apply(这是参数); var providerName=参数[0]; var directiveName=(providerName.match(/(.+)DirectiveProvider$/)| |[])[1]; if(directiveName){ var$get=provider.$get; log(['hi from injector get',arguments[0],provider.$get]); provider.$get=已修补的函数$get(){ var实例=$get.apply(这是参数); log(['hi from provider$get',providerName,instances]); angular.forEach(实例,函数(实例){ 函数getPatchedPostlink(postlink){ 返回函数patchedPostlink(范围、元素、属性、ctrls){ var_postlink=postlink; log(['hi from directive link',directiveName,scope,element,attrs,ctrls]); //来了 if(scope.$$isolateBindings&&instance.scopeRequired){ var bindings=scope.$$isolateBindings; angular.forEach(instance.scopeRequired,函数(scopeVar){ 如果(!bindings[scopeVar]| |!attrs.hasOwnProperty(bindings[scopeVar.attrName)){ 抛出新错误(“未分配指令“+directiveName+”所需的范围变量“+scopeVar+””); } }); } 返回angular.isFunction(_postlink)?_postlink.apply(此参数):未定义; }; } var_compile=instance.compile; //如果存在“编译”,则“链接”无效 如果(_编译){ instance.compile=函数patchedcomile(元素,属性){ var compile=\u compile.apply(实例、参数); log(['hi from directive compile',directiveName,this,element,attrs]); 如果(!编译){ 编译={}; }else if(angular.isFunction(compile)){ compile={post:compile}; } //compile.pre=getPatchedPrelink(compile.pre); compile.post=getPatchedPostlink(compile.post); 返回编译; }; }否则{ instance.link=getPatchedPostlink(instance.link); } },这个); 返回实例; }; } 退货供应商; }; }]);
我已经这样做了,但是如果我像
一样使用指令,当
是必需的并且被定义为隔离作用域的
=
时,这会引发错误吗?事实上,我自己没有测试这个问题……我的错是,我没有仔细阅读这个问题。不,它不会抛出它,如果您试图分配无效的范围变量,它将抛出一个错误。我已经更新了答案,希望它能有所帮助。现在这是一个有趣的解决方案:)它很详细,但对于monkey补丁用户定义(但不是ng)指令来说效果很好。