使用 ControllerAs 时 Angular 嵌套指令出现问题
Trouble with Angular Nested Directives when using ControllerAs
我正在构建一个巨大的表单,它调用各种指令来构建一个完整的表单。调用表单生成器的主页传递 ng-model 数据,如下所示:
<div form-builder form-data=“formData”></div>
然后表单生成器页面调用各种 child 指令来构建表单的各个部分:
FormBuilder.html:
<div form-fields></div>
<div photo-fields></div>
<div video-fields></div>
.. etc.. etc...
在控制器中使用 $scope
时,我在 child 指令中访问 $scope
没有问题,如下所示:
function formBuilder() {
return {
restrict: 'A',
replace: true,
scope: {
formData: '='
},
templateUrl: 'FormBuilder.html',
controller: function($scope) {
$scope.formSubmit = function() {
// Submits the formData.formFields and formData.photoFields
// to the server
// The data for these objects are created through
// the child directives below
}
}
}
}
function formFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'FormFields.html',
controller: function($scope) {
console.log($scope.formData.formFields);
}
}
}
function photoFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'PhotoFields.html',
controller: function($scope) {
console.log($scope.formData.photoFields);
}
}
}
... etc..
但是自从我摆脱了 $scope
并开始使用 ControllerAs
之后,我在使用 Parent - [=63= 访问 2 方式绑定时遇到了各种麻烦] 控制器。
function formBuilder() {
return {
restrict: 'A',
replace: true,
scope: {
formData: '='
},
templateUrl: 'FormBuilder.html',
controller: function() {
var vm = this;
console.log(vm.formData); // Its fine here
vm.formSubmit = function() {
// I cannot change formData.formFields and formData.photoFields
// from Child Directive "Controllers"
}
},
controllerAs: ‘fb’,
bindToController: true
}
}
function formFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'FormFields.html',
controller: function() {
var vm = this;
console.log(vm.formData.formFields);
// No way to access 2 way binding with this Object!!!
}
}
}
function photoFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'PhotoFields.html',
controller: function() {
var vm = this;
console.log(vm.formData.photoFields);
// No way to access 2 way binding with this Object!!!
}
}
}
无论我尝试什么,我都遇到了障碍。我尝试过的事情是:
- 独立作用域:我尝试传递
formData.formFields
和
formData.photoFields
作为 child 指令的独立作用域,
但我最终得到 $compile: MultiDir
错误由于
嵌套的隔离范围,所以这是不可能的。
- 如果我没有
每个表单部分的单独指令,并将它们全部放在
formBuilder
指令下的 1 指令,则变为
巨大的指令。以上只是草图,但每个 child
指令最终构建了 1 个大表格。所以合并它们
在一起真的是最后的手段,因为它确实变得很难
维护和不可读。
- 我认为没有办法访问
Parent 指令的
ControllerAs
来自 Child 指令的 Controller
任何其他方式
从我到目前为止所看到的。
- 如果我使用 parent 的 ControllerAs
child 指令模板的 ng-model 就像
<input type=“text” ng-model=“fb.formData.formFields.text" />
,工作正常,但我
需要从 Child 指令的控制器访问相同的
一些我无法做的处理。
- 如果我摆脱
controllerAs
并再次使用 $scope
,它像以前一样工作,但我
试图完全摆脱 $scope
为自己做好准备
未来 Angular 变化。
由于它是一种高级表单,我需要有单独的指令来处理各种表单部分,并且由于自 Angular 1.2 以来不允许使用嵌套的独立作用域,因此它变得越来越难,尤其是在尝试获取时使用 ControllerAs
.
摆脱 $scope
有人可以指导我这里有哪些选择吗?感谢您阅读我的长文 post.
基本上你需要使用指令的require
选项(require
选项用于指令与指令的通信)。这将通过在子指令中提及 require
选项来访问其父控制器。您还需要使用 bindToController: true
,它基本上会将独立的范围数据添加到指令控制器。
代码
function formBuilder() {
return {
restrict: 'A',
replace: true,
bindToController: true,
scope: {
formData: '='
},
templateUrl: 'FormBuilder.html',
controller: function($scope) {
$scope.formSubmit = function() {
// Submits the formData.formFields and formData.photoFields
// to the server
// The data for these objects are created through
// the child directives below
}
}
}
}
然后你需要给子指令添加require
选项。基本上 require
选项将有 formBuilder
指令和 ^
(表示 formBuilder
将在父元素中),如 require: '^formBuilder',
.
通过编写 require
选项,您可以在 link 函数的第 4 个参数中获取该指令的控制器。
代码
function formFields() {
return {
restrict: 'A',
replace: true,
require: '^formBuilder',
templateUrl: 'FormFields.html',
//4th parameter is formBuilder controller
link: function(scope, element, attrs, formBuilderCtrl){
scope.formBuilderCtrl = formBuilderCtrl;
},
controller: function($scope, $timeout) {
var vm = this;
//getting the `formData` from `formBuilderCtrl` object
//added timeout here to run code after link function, means after next digest
$timeout(function(){
console.log($scope.formBuilderCtrl.formData.formFields);
})
}
}
}
function photoFields() {
return {
restrict: 'A',
replace: true,
require: '^formBuilder',
templateUrl: 'PhotoFields.html',
//4th parameter is formBuilder controller
link: function(scope, element, attrs, formBuilderCtrl){
scope.formBuilderCtrl = formBuilderCtrl;
},
controller: function($scope, $timeout) {
var vm = this;
console.log(vm.formData.photoFields);
//to run the code in next digest cycle, after link function gets called.
$timeout(function(){
console.log($scope.formBuilderCtrl.formData.formFields);
})
}
}
}
编辑
上述解决方案的一个问题是,为了在指令控制器中访问父指令的控制器,我做了一些技巧。 1st 将 formBuilderCtrl
包含到 link 函数第四个参数的范围变量。然后只有您可以使用 $scope
(您不想在那里)访问该控制器。关于 Github with open status 中记录的相同问题,您可以在此处查看。
我正在构建一个巨大的表单,它调用各种指令来构建一个完整的表单。调用表单生成器的主页传递 ng-model 数据,如下所示:
<div form-builder form-data=“formData”></div>
然后表单生成器页面调用各种 child 指令来构建表单的各个部分:
FormBuilder.html:
<div form-fields></div>
<div photo-fields></div>
<div video-fields></div>
.. etc.. etc...
在控制器中使用 $scope
时,我在 child 指令中访问 $scope
没有问题,如下所示:
function formBuilder() {
return {
restrict: 'A',
replace: true,
scope: {
formData: '='
},
templateUrl: 'FormBuilder.html',
controller: function($scope) {
$scope.formSubmit = function() {
// Submits the formData.formFields and formData.photoFields
// to the server
// The data for these objects are created through
// the child directives below
}
}
}
}
function formFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'FormFields.html',
controller: function($scope) {
console.log($scope.formData.formFields);
}
}
}
function photoFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'PhotoFields.html',
controller: function($scope) {
console.log($scope.formData.photoFields);
}
}
}
... etc..
但是自从我摆脱了 $scope
并开始使用 ControllerAs
之后,我在使用 Parent - [=63= 访问 2 方式绑定时遇到了各种麻烦] 控制器。
function formBuilder() {
return {
restrict: 'A',
replace: true,
scope: {
formData: '='
},
templateUrl: 'FormBuilder.html',
controller: function() {
var vm = this;
console.log(vm.formData); // Its fine here
vm.formSubmit = function() {
// I cannot change formData.formFields and formData.photoFields
// from Child Directive "Controllers"
}
},
controllerAs: ‘fb’,
bindToController: true
}
}
function formFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'FormFields.html',
controller: function() {
var vm = this;
console.log(vm.formData.formFields);
// No way to access 2 way binding with this Object!!!
}
}
}
function photoFields() {
return {
restrict: 'A',
replace: true,
templateUrl: 'PhotoFields.html',
controller: function() {
var vm = this;
console.log(vm.formData.photoFields);
// No way to access 2 way binding with this Object!!!
}
}
}
无论我尝试什么,我都遇到了障碍。我尝试过的事情是:
- 独立作用域:我尝试传递
formData.formFields
和formData.photoFields
作为 child 指令的独立作用域, 但我最终得到$compile: MultiDir
错误由于 嵌套的隔离范围,所以这是不可能的。 - 如果我没有
每个表单部分的单独指令,并将它们全部放在
formBuilder
指令下的 1 指令,则变为 巨大的指令。以上只是草图,但每个 child 指令最终构建了 1 个大表格。所以合并它们 在一起真的是最后的手段,因为它确实变得很难 维护和不可读。 - 我认为没有办法访问
Parent 指令的
ControllerAs
来自 Child 指令的Controller
任何其他方式 从我到目前为止所看到的。 - 如果我使用 parent 的 ControllerAs
child 指令模板的 ng-model 就像
<input type=“text” ng-model=“fb.formData.formFields.text" />
,工作正常,但我 需要从 Child 指令的控制器访问相同的 一些我无法做的处理。 - 如果我摆脱
controllerAs
并再次使用$scope
,它像以前一样工作,但我 试图完全摆脱$scope
为自己做好准备 未来 Angular 变化。
由于它是一种高级表单,我需要有单独的指令来处理各种表单部分,并且由于自 Angular 1.2 以来不允许使用嵌套的独立作用域,因此它变得越来越难,尤其是在尝试获取时使用 ControllerAs
.
$scope
有人可以指导我这里有哪些选择吗?感谢您阅读我的长文 post.
基本上你需要使用指令的require
选项(require
选项用于指令与指令的通信)。这将通过在子指令中提及 require
选项来访问其父控制器。您还需要使用 bindToController: true
,它基本上会将独立的范围数据添加到指令控制器。
代码
function formBuilder() {
return {
restrict: 'A',
replace: true,
bindToController: true,
scope: {
formData: '='
},
templateUrl: 'FormBuilder.html',
controller: function($scope) {
$scope.formSubmit = function() {
// Submits the formData.formFields and formData.photoFields
// to the server
// The data for these objects are created through
// the child directives below
}
}
}
}
然后你需要给子指令添加require
选项。基本上 require
选项将有 formBuilder
指令和 ^
(表示 formBuilder
将在父元素中),如 require: '^formBuilder',
.
通过编写 require
选项,您可以在 link 函数的第 4 个参数中获取该指令的控制器。
代码
function formFields() {
return {
restrict: 'A',
replace: true,
require: '^formBuilder',
templateUrl: 'FormFields.html',
//4th parameter is formBuilder controller
link: function(scope, element, attrs, formBuilderCtrl){
scope.formBuilderCtrl = formBuilderCtrl;
},
controller: function($scope, $timeout) {
var vm = this;
//getting the `formData` from `formBuilderCtrl` object
//added timeout here to run code after link function, means after next digest
$timeout(function(){
console.log($scope.formBuilderCtrl.formData.formFields);
})
}
}
}
function photoFields() {
return {
restrict: 'A',
replace: true,
require: '^formBuilder',
templateUrl: 'PhotoFields.html',
//4th parameter is formBuilder controller
link: function(scope, element, attrs, formBuilderCtrl){
scope.formBuilderCtrl = formBuilderCtrl;
},
controller: function($scope, $timeout) {
var vm = this;
console.log(vm.formData.photoFields);
//to run the code in next digest cycle, after link function gets called.
$timeout(function(){
console.log($scope.formBuilderCtrl.formData.formFields);
})
}
}
}
编辑
上述解决方案的一个问题是,为了在指令控制器中访问父指令的控制器,我做了一些技巧。 1st 将 formBuilderCtrl
包含到 link 函数第四个参数的范围变量。然后只有您可以使用 $scope
(您不想在那里)访问该控制器。关于 Github with open status 中记录的相同问题,您可以在此处查看。