2014-01-09 90 views
0

我正在尝试为自定义输入组件创建一些自定义验证。AngularJS:控制器 - 指令双向通信

自定义输入的指令将充当黑盒,因此我可以从控制器添加我想要的验证。

要做到这一点我想补充的指令的属性,所谓的“验证”,PE:

<custom-input validations="checkEmail() checkIsNotUsed()" type="text" placeholder="Email"></custom-input> 

有了这个例子,我可以从控制器定义我的验证,因为我想,有这个想法,当我想从控制器提交,它会检查这个组件是否验证'checkEmail()'和'checkIsNotUsed()'。为此,我需要控制器和内部指令p.e.之间的双向通信。使用电子邮件:

  1. 控制器想验证组件,所以它会调用内部指令来获取内部输入元素。
  2. 指令将输入返回给控制器。
  3. 控制器可以根据链接到他的验证检查输入。

我尝试过不同的方法,但我无法获得最终目标。

Here is the example I've been working with

编辑

解决:http://plnkr.co/edit/DMUVLifuWeGEuXOVfRwE?p=preview

回答

1

我会稍有怀疑你是否需要该指令作为一个完整的黑盒子。首先,通常您需要一些验证消息或一些向用户显示的有关无效数据的不同情况的信息,因此仅仅验证者的真/假返回值是不够的。其次,你还重新创建的很多事情已经角让你与ngFormngModelngModelControllerinput指令,特别是ngModelController

$setValidity功能我会把每个校验器在其自己的指令,require小号ngModel:一个用于电子邮件,另一个用于密码。尽管如此,您仍然可以从整体控制器传递选项,但每个指令都是根据所需信息量身定制的。例如,validationEmail指令可以接受使用的现有的邮件的数组:

<input validation-email validation-email-used="usedEmails" ng-model="data.email" type="text" placeholder="Email" name="email" ng-required /> 

哪里usedEmails是电子邮件的阵列。该指令可以写成:

app.directive('validationEmail', function() { 
    return { 
    require: 'ngModel', 
    scope: { 
     validationEmailUsed:'=' 
    }, 
    link: function(scope, element, attributes, ngModelController) { 
     scope.$watch(function() { 
     return ngModelController.$viewValue 
     }, function(email) { 
     // Test the email and call 
     // ngModelController.$setValidity(...) 
     // to set the validity of the email 
     }); 
    } 
    }; 
}); 

您可以在modified version of your Plunker

编辑看到这个动作:如果要与服务器端验证,一旦所有客户端验证已经从通过整合指令,可以从传递给ngSubmit表单上功能做到这一点:

<form name="myForm" ng-submit="submit()"> 

可使用的形式将自己暴露于范围的事实进行编码时,其所有ngModel控制器(用于相同的例如,使用$timeout,而不是调用$http或服务),

$scope.submit = function() { 
$timeout(function() { 
    $scope.myForm.username.$setValidity('available',false); 
    $scope.myForm.email.$setValidity('emailFree',false); 
    },500); 
} 

与这样的一个问题是,你再会要标记的输入为有效用户改变后。您可以创建一个validOnChange指令,将用作:

<input ng-model="data.username" type="text" placeholder="Username" name="username" valid-on-change="available" ng-required /> 

,并编写了如:

app.directive('validOnChange', function() { 
    return { 
    require: 'ngModel', 
    scope: '', 
    link: function(scope, element, attributes, ngModelController) { 
     scope.$watch(function() { 
     return ngModelController.$viewValue 
     }, function() { 
     ngModelController.$setValidity(attributes.validOnChange,true); 
     }); 
    } 
    } 
}); 

你可以see this in this Plunker

使用ngForm和ngModelController的另一个一般好处是,它根据输入的错误/有效状态向窗体和元素添加了很多类,并在范围中显示错误状态,所以您可以例如,使用ngIf可轻松显示/隐藏错误消息。

+0

这很好,但我仍然觉得我不想验证,直到我点击提交。就可伸缩性而言,这种方法还不够好,想象一下,如果字段是有效的,我希望明天检查我的后端,我不想每次输入时都要验证,但当我点击提交时。所以我的问题是,在Angular中,点击提交时可能触发该操作? – DreaMTT

+0

此外,使用您的解决方案,我不能使用指令来自定义输入,我将需要。我试着编辑你的plunkr,使用嵌套的指令,但不知何故,我无法与验证内部输入沟通。如果你可以检查一下,并摆脱一些ligth,我会很感激它:http://plnkr.co/edit/DB0a3rjaRhKk7NV4dt5v?p =预览非常感谢您的帮助! – DreaMTT

+0

@DreaMTT我已经修改了我的答案,显示了如何在表单通过客户端验证并从指令中提交给服务器之后仍然可以设置有效性。 –