使用ControllerAs时出现Angular Nested Directive问题

时间:2015-12-06 10:58:17

标签: angularjs angularjs-directive angularjs-scope angular-controller angularjs-controlleras

我正在构建一个巨大的表单,它调用各种指令来构建完整的表单。调用表单生成器的主页传递ng模型数据,如下所示:

body

然后,Form Builder Page调用各种子指令来构建Form的各个部分:

<div form-builder form-data=“formData”></div>

在控制器中使用FormBuilder.html: <div form-fields></div> <div photo-fields></div> <div video-fields></div> .. etc.. etc... 时,访问子指令中的$scope是没有问题的:

$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

无论我尝试什么,我都会遇到路障。我尝试过的事情是:

  1. 隔离范围:我尝试传递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作为child指令的独立范围, 但是我最终得到了formData.photoFields错误 嵌套的隔离范围,因此无法实现。
  2. 如果我没有 每个表单部分的单独指令,并将所有表单部分包含在内 在$compile: MultiDir指令下的1指令,然后它变成了 无耻的指示。以上只是一个草图,但每个孩子 指令构建最终放在一起的1大表。所以合并他们 一起真的是最后的手段,因为它变得很难 维持和不可读。
  3. 我认为没有办法访问 来自Child Directive的formBuilder的父指令ControllerAs以任何其他方式 从我到目前为止看到的。
  4. 如果我使用父母的ControllerAs 儿童指令模板的ng-model像Controller一样,工作正常,但我 需要从Child指令的控制器访问相同的 一些我无法做的处理。
  5. 如果我摆脱了 <input type=“text” ng-model=“fb.formData.formFields.text" />然后再次使用controllerAs,它就像以前一样,但我是 试图完全摆脱$scope为自己做好准备 未来的角度变化。
  6. 由于它是一个高级表单,我需要有单独的指令来处理各种表单部分,因为自Angular 1.2以来不允许嵌套的隔离作用域,所以它使得它变得更加困难,尤其是在试图摆脱{{1}时使用$scope

    有人可以指导我在这里有什么选择吗?我感谢你阅读我的长篇文章。

1 个答案:

答案 0 :(得分:2)

基本上你需要使用require指令选项(require选项用于指令的通信指令)。只需在child指令中提及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选项,您可以在链接函数4th参数中获取该指令的控制器。

<强>代码

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包含来自link function 4th参数的范围变量的formBuilderCtrl。然后,只有您可以使用$scope(您不希望在那里)访问该控制器。关于Github with open status中记录的同一问题,您可以在此处查看。