2017-10-09 100 views
0

我正在关注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); 
      }; 
     } 
    }; 
}]) 
+0

你尝试声明'mainnav '作为指令而不是组件? –

+2

为什么不把'mainnav'的引用传递给'menuToggle'就像'scope: {section:'=',context:'='}' 并且在你的'main-nav。htm' do'' – AdityaParab

+0

通常对于组件,访问父控制器的可接受方式是使用'require'属性。有关更多信息,请参阅[AngularJS开发人员指南 - 组件间通信](https://docs.angularjs.org/guide/component#intercomponent-communication) – georgeawg

回答

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>

编辑::

功能$scope.isOpen$scope.toggle也不必要。 (除非你有一些具体的要求,让他们你现在的样子)

在你main-nav-li.htm无论你在哪里找到isOpen()替换成context.isOpen(section)何地,只要你有toggle(),替换与context.toggle(section)

+0

再次感谢! –

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/

+0

我缩小了我的示例代码,所以我需要进行一些调整,但是谢谢,我会再去 –