无法访问元素父控制器

时间:2017-10-09 15:21:47

标签: javascript angularjs

我正在关注tutorial以使用AngularJS sidenav实施下拉菜单。我在我的应用程序中使用了组件,因此我的布局与提供的示例不同。

ul填充了存储在对象中的名称,但功能失败。我缩小它来解决错误是由于无法找到指令父元素控制器。

var controller = $element.parent().controller();

当我在控制台中记录controller时,它应显示以下控制器功能:

vm.isOpen = isOpen;
vm.toggleOpen = toggleOpen;
vm.autoFocusContent = false;
vm.menu = mainNavService;
vm.status = {
    isFirstOpen: true,
    isFirstDisabled: false
};

但它返回并清空对象。是因为而不是使用控制器,我在模块上使用Angular的组件方法并使用控制器属性?

问题

为什么在尝试访问控制器时,它不返回任何属性?

app.component('mainnav', {
    templateUrl: 'p3sweb/app/components/app/views/main-nav.htm',
    controller: ['userService', 'mainNavService', function(userService, mainNavService){

        var vm = this;

        vm.isOpen = isOpen;
        vm.toggleOpen = toggleOpen;
        vm.autoFocusContent = false;
        vm.menu = mainNavService;
        vm.status = {
          isFirstOpen: true,
          isFirstDisabled: false
        };
        function isOpen(section) {
            console.log('menu.isSectionSelected(section)')
          return menu.isSectionSelected(section);
        }
        function toggleOpen(section) {
                console.log(menu.toggleSelectSection(section))
          menu.toggleSelectSection(section);
        }
    }]
})

app.directive('menuToggle', [ '$timeout', function($timeout){
    return {
        scope: {
            section: '='
        },
        templateUrl: 'p3sweb/app/components/app/views/main-nav-li.htm',
        link: function($scope, $element) {

            var controller = $element.parent().controller(); //FAILS

            $scope.isOpen = function() {
                return controller.isOpen($scope.section)
            };
            $scope.toggle = function() {
                console.log(controller.toggleOpen())
                controller.toggleOpen($scope.section);
            };
        }
    };
}])

2 个答案:

答案 0 :(得分:1)

javascript上下文可以很容易地传递。你可以做的是改变你的menuToggle指令,如

app.directive('menuToggle', [ '$timeout', function($timeout){
    return {
        scope: {
            section: '=',
            context: '=' // NOTE: This is what the parent component will pass
        },
        templateUrl: 'p3sweb/app/components/app/views/main-nav-li.htm',
        link: function($scope, $element) {
            var controller = $scope.context; // This is reference to parent
            $scope.isOpen = function() {
                return controller.isOpen($scope.section)
            };
            $scope.toggle = function() {
                console.log(controller.toggleOpen())
                controller.toggleOpen($scope.section);
            };
        }
    };
}])

在你需要做的main-nav.htm

<menu-toggle section="blah" context="$ctrl"></menu-toggle>

EDIT ::

功能$scope.isOpen$scope.toggle也是不必要的。 (除非你有一些特定的要求,让你按现在的方式拥有它们)

main-nav-li.htm找到isOpen()的任何地方,将其替换为context.isOpen(section)以及toggle()的任何地方,将其替换为context.toggle(section)

答案 1 :(得分:0)

我在jsfiddle运行你的代码,这就是我改变了:

首先,我将组件更改为添加transclude选项的指令:

app.directive('mainnav', function(){
    return {
      transclude: true,
      template: '<div> <ng-transclude></ng-transclude> <div>',
      controller: ['$scope', function($scope){
          var vm = this;
          vm.autoFocusContent = false;
          vm.status = {
            isFirstOpen: true,
            isFirstDisabled: false
          };

      }]
    }
});

在此之后,您可以像这样访问父控制器:

var controller = $element.parent().controller('mainnav');

以下是完整示例:

https://jsfiddle.net/jm65ajjz/2/