将forms传递给指令

我想封装我的表单字段在一个指令,所以我可以简单地这样做:

<div ng-form='myForm'> <my-input name='Email' type='email' label='Email Address' placeholder="Enter email" ng-model='model.email' required='false'></my-input> </div> 

我如何访问myForm在我的指令,所以我可以做validation检查,例如myForm.Email.$valid

在指令中访问FormController:

 require: '^form', 

那么它将作为你的链接函数的第四个参数:

 link: function(scope, element, attrs, formCtrl) { console.log(formCtrl); } 

小提琴

你可能只需要访问NgModelController:

 require: 'ngModel', link: function(scope, element, attrs, ngModelCtrl) { console.log(ngModelCtrl); } 

小提琴

如果您需要访问两者:

 require: ['^form','ngModel'], link: function(scope, element, attrs, ctrls) { console.log(ctrls); } 

小提琴

这里有一个完整的例子: http : //plnkr.co/edit/W1KxuL?p=preview (使用Bootstrap 3.1进行样式化)

它包含一个包含多个input(姓名,电子邮件,年龄和国家)的表单。 姓名,电子邮件和年龄是指令。 国家是一个“常规”的投入。

对于每个input都显示一个帮助信息,当用户没有input正确的值。

该表单包含一个保存button,如果表单至less包含一个错误,则该button将被禁用。

AngularJS形式与指令

编辑2:我会留下我的答案,因为这可能有助于其他原因,但马克Rajcok其他答案是我原本想做的,但没有去工作。 显然这里的父控制器是form ,而不是ngForm


你可以在你的指令中使用一个属性来传递它,尽pipe这样会变得相当冗长。

这是一个工作,简化的jsFiddle 。

HTML:

 <div ng-form="myForm"> <my-input form="myForm"></my-input> </div> 

指令的基本部分:

 app.directive('myInput', function() { return { scope: { form: '=' }, link: function(scope, element, attrs) { console.log(scope.form); } }; }); 

发生了什么

我们要求Angular通过使用'='form属性中指定的范围值绑定到我们的隔离范围。

这样做可以将input指令中的实际表单分离出来。

注意:我试过使用require: "^ngForm" ,但ngForm指令没有定义控制器,也不能以这种方式使用(这太糟糕了)。


所有这一切,我认为这是一个非常详细和杂乱的方式来处理这个问题。 向表单元素添加新的指令可能会更好,并使用require来访问该项目。 我会看看我能不能把东西放在一起。

编辑:使用父指令

好的,下面是我可以用父指令找出的最好的答案,我会在第二个章节解释一下:

使用父指令工作jsFiddle

HTML:

 <div ng-app="myApp"> <div ng-form="theForm"> <my-form form="theForm"> <my-input></my-input> </my-form> </div> </div> 

JS(部分):

 app.directive('myForm', function() { return { restrict: 'E', scope: { form: '=' }, controller: ['$scope', function($scope) { this.getForm = function() { return $scope.form; } }] } }); app.directive('myInput', function() { return { require: '^myForm', link: function(scope, element, attrs, myForm) { console.log(myForm.getForm()); } }; }); 

这将表单存储在父指令范围( myForm )中,并允许子指令通过要求父表单( require: '^myForm' )并在链接函数( myForm.getForm() )中访问指令的控制器来访问它。

优点:

  • 你只需要在一个地方识别表格
  • 您可以使用父母控制器来存放通用代码

劣势:

  • 你需要一个额外的节点
  • 您需要将表单名称放入两次

我更喜欢什么

我试图使用表单元素上的属性来工作。 如果这工作,你只需要添加指令到ngForm相同的元素。

然而,我得到了一些奇怪的行为与范围,其​​中myFormNamevariables将在$scope可见,但是当我试图访问它将是undefined 。 那个让我困惑。

从AngularJS 1.5.0开始,有更清晰的解决scheme(而不是直接使用linkfunction)。 如果你想在你的子组件的指令控制器中访问一个表单的FormController ,那么你可以简单地敲击指令的require属性,如下所示:

 return { restrict : 'EA', require : { form : '^' }, controller : MyDirectiveController, controllerAs : 'vm', bindToController : true, ... }; 

接下来,您将能够像在其他任何范围variables中那样,在模板或指令控制器中访问它, 例如

 function MyDirectiveController() { var vm = this; console.log('Is the form valid? - %s', vm.form.$valid); } 

请注意,为此,您还需要在指令上设置bindToController: true属性。 有关更多信息,请参阅$compile的文档和此问题。

文档中的相关部分:

要求

需要另一个指令,并将其控制器作为链接函数的第四个参数。 require属性可以是string数组对象

如果require属性是一个对象,并且bindToController是真的,那么所需的控制器使用require属性的键绑定到控制器。 如果所需控制器的名称与本地名称(键)相同,则名称可以省略。 例如, {parentDir: '^parentDir'}等价于{parentDir: '^'}

使你的'我更喜欢'小提琴的工作! 出于某种原因,您可以在console.log中看到“$ scope.ngForm”string,但直接logging不起作用,导致未定义。 但是,如果将属性传递给控制器​​function,则可以获取它。

 app.directive('myForm', function() { return { restrict: 'A', controller: ['$scope','$element','$attrs', function($scope,$element,$attrs) { this.getForm = function() { return $scope[$attrs['ngForm']]; } }] } }); 

http://jsfiddle.net/vZ6MD/20/