将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将被禁用。
编辑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
相同的元素。
然而,我得到了一些奇怪的行为与范围,其中myFormName
variables将在$scope
可见,但是当我试图访问它将是undefined
。 那个让我困惑。
从AngularJS 1.5.0开始,有更清晰的解决scheme(而不是直接使用link
function)。 如果你想在你的子组件的指令控制器中访问一个表单的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']]; } }] } });