2017-10-09 99 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

我縮小了我的示例代碼,所以我需要進行一些調整,但是謝謝,我會再去 –