如何从AngularJS中的多级指令获取控制器范围(没有$ parent)

时间:2017-11-29 07:46:53

标签: javascript angularjs angularjs-directive angularjs-scope

如何从以下结构中的多级指令访问控制器范围:

我创建了一个在其内部具有多级范围的指令。

 1. Controller scope
 1.2. Directive1 scope(main directive)
 1.2.1. Directive2 scope
 1.2.1.1 Directive3 scope

我想从指令3中获取控制器范围。

请不要引用$ parent,因为父级别不确定,用户可以在另一个指令中使用此指令。(参见下面的代码)

<div ng-controller="Test">
   <custom-dir>
      <dir1>
         <dir2>
            <dir3>
            </dir3>
          </dir2>
       </dir1>
    <custom-dir>
</div>

用户在Test控制器中创建一个函数,该函数将在我的Directive 3范围内调用(如何获取控制器范围?)。

<div ng-controller="Test">
     <dir1>
         <dir2>
             <dir3>
             </dir3>
         </dir2>
     </dir1>
</div>

更多详细信息(请不要参考语法错误):

控制器是:

App.controller('ScopeController', function ($scope, $rootScope, $uibModal, $http, $filter, $cookieStore, Common, $cookies) {
    $scope.runTest = function () {
        return `<input type='button' ng-click='testHtml()' value='Test'/>`;
    }
    $scope.testHtml = function () {
        alert("work");
    }
    $scope.model=someModel;
    $scope.config=someConfig;
    $scope.columns={html: $scope.runTest};
});

dir1指令:

App.directive("dir1", function ($compile, $filter, $rootScope, $timeout, Common, $window, $http) {
    return {
        restrict: "E",
        priority: 1,
        terminal: false,
        templateUrl: "Content/html/Table.html?version=2.6",
        scope: {
            model: "=",
            columns: "=",
            config: "=",
            search: "@",
        },
        link: function (scope, elem, attrs) {
            scope.CallFunc = function (html) {
                if (typeof (html) =="function" )
                    return html();
                else {
                    return scope.$parent.$eval(html + "()", {});
                }
            }
        }
    }
});

动态指令编译runTest输出

App.directive('dynamic', function ($compile) {
    return {
        restrict: 'A',
        replace:true,
        link: function (scope, ele, attrs) {
            scope.$watch(attrs.dynamic, function (html) {
                ele.html(html);
                $compile(ele.contents())(scope);
            });
        }
    };
});

如果我将行$compile(ele.contents())(scope);更改为$compile(ele.contents())(scope.$parent.$parent);它的工作。

在这个指令中,我需要获得没有$ parent的控制器范围,因为 一些用户可以在下面的另一个指令中使用该指令:

<custom-dir>
    <dir1 model="model" columns="columns" config="config">
        <div dynamic="CallFunc(columns.html)"></div>
    </dir1>
</custom-dir>

使用HTML标记

<dir1 model="model" columns="columns" config="config">
    <div dynamic="CallFunc(columns.html)"></div>
</dir1>

2 个答案:

答案 0 :(得分:2)

此问题处理以下代码:

用于存储控制器范围的服务:

App.service('TableService', function () {
        return {
            MyScope: null
        };
    });

将TableService注入动态指令(该指令编译动态内容):

App.directive('dynamic', function ($compile,TableService) {
    return {
        restrict: 'A',
        replace:true,
        link: function (scope, ele, attrs) {
            scope.$watch(attrs.dynamic, function (html) {
                ele.html(html);
                $compile(ele.contents())(TableService.MyScope);
            });
        }
    };
});

最后在控制器中:

App.controller('ScopeController', function ($scope, $rootScope, $uibModal, 
              $http, $filter, $cookieStore, Common, $cookies,TableService) {
    TableService.myScope = $scope;        
    $scope.runTest = function () {
        return `<input type='button' ng-click='testHtml()' value='Test'/>`;
    }
    $scope.testHtml = function () {
        alert("work");
    }
    $scope.model=someModel;
    $scope.config=someConfig;
    $scope.columns={html: $scope.runTest};
});

之后,动态指令可以访问控制器范围,即使指令放入另一个指令(不使用$ parent),也会调用所有动态事件(如testHtml)。

谢谢你@shaunhusainhuan feng给了我一个主意。

答案 1 :(得分:1)

在子控制器中执行以下操作:

TableView<S>

在父控制器中执行监听器:

$scope.$broadcast('yourEvent');