Reputation: 1220
I am following a tutorial to implement a drop down menu with AngularJS's sidenav
. I have used components in my application so my layout differs from the example provided.
The ul
is populated with the names stored in an object, but the functions are failing. I am narrowed it down to work out the error is due to not being able to find the directives parent elements controller.
var controller = $element.parent().controller();
When I log controller
in the console, it should display the controllers functions which are:
vm.isOpen = isOpen;
vm.toggleOpen = toggleOpen;
vm.autoFocusContent = false;
vm.menu = mainNavService;
vm.status = {
isFirstOpen: true,
isFirstDisabled: false
};
But instead it returns and empty object. Is it because rather than use a controller, I am using Angular's component method on the module and using the controller property?
Question
Why when trying to access the controller, it returns no properties?
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);
};
}
};
}])
Upvotes: 0
Views: 67
Reputation: 7100
A javascript context can be passed around pretty easily. What you can do is, in change your menuToggle
directive like
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);
};
}
};
}])
And Inside your main-nav.htm
you need to do
<menu-toggle section="blah" context="$ctrl"></menu-toggle>
EDIT::
The functions $scope.isOpen
and $scope.toggle
are also unnecessary. (unless you have some specific requirement to have them the way you have now)
In your main-nav-li.htm
Wherever you find isOpen()
replace that with context.isOpen(section)
and wherever you have toggle()
, Replace that with context.toggle(section)
Upvotes: 1
Reputation: 599
I ran your code in jsfiddle and this is what I changed:
First I changed the component to a directive adding the transclude
option:
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
};
}]
}
});
After this you can access the parent controller like this:
var controller = $element.parent().controller('mainnav');
Here is the full example:
https://jsfiddle.net/jm65ajjz/2/
Upvotes: 0