Question

I want to make a categories tree with checkboxs (which is a recusive list) directive.

I did a directive called categoriesTreeContainer that containes all the list of categories

and I did another directive called categoryItem that containes the category item which is the child of categoriesTreeContainer

this is what I did categoriesTreeContainer:

myApp.directive('categoriesTreeContainer', function(){
return {
    restrict : 'E',
    template : '<category-item ng-repeat="category in categoriesTree" category="category"></category-item>',
    scope    : {
        categoriesTree : "=categoriestree",
        selectedCategories : "=ngModel",
    },

    controller : function($scope, $element, $attrs){
        $scope.selectedCategories = [];

        $scope.onSelectionChange = function(category){
            console.log('yah');
        }
    }
}

})

for the categoryItem:

myApp.directive('categoryItem', function($compile){
return {
    require: '^categoriesTreeContainer',
    restrict : 'E',
    //replace  : true,
    transclude : true,
    scope    : {
        category : "=category"
    },
    link     : function(scope, element, attrs, categoriesTreeCtrl){
        console.log(categoriesTreeCtrl);

        if(scope.category.subCategories.length>0){

            element.append($compile(
                '<div class="panel panel-default panel-treelist">'+
                '<div class="panel-heading"><h4 class="panel-title">'+
                '<label data-toggle="collapse" data-target="#{{category.$$hashKey}}">'+
                '<input type="checkbox" ng-change="categoriesTreeCtrl.onSelectionChange(category)"  ng-model="category.selected" />'+
                ' {{category.name}}</label></h4></div><div id="{{category.$$hashKey}}" class="panel-collapse collapse">'+
                '<div class="panel-body">'+
                '<category-item id="{{category.$$hashKey}}" ng-repeat="subCategory in category.subCategories" category="subCategory" categoriestree="categoriesTree" ng-model="selectedCategories">'+
                '</category-item></div></div></div>'
                )(scope))
        }else{
            element.append($compile('<label><input ng-change="categoriesTreeCtrl.onSelectionChange(category)" type="checkbox" ng-model="category.selected"> {{category.name}}</label><br/>')(scope));
        }
    }
}

})

and in the DOM:

<categories-tree-container categoriestree="categoriesTree" ng-model="selectedCategories"></categories-tree-container>

The tree is rendered as I wanted. The problem is that the required controller '^categoriesTreeContainer' in the categoryItem directive is void. I did a console.log(categoriesTreeCtrl) for the categoriesTreeCtrl in the link function and this what is what I get:

c {}, A void object.

What am I doing wrong?

Was it helpful?

Solution

The categoriesTreeCtrl will be void object because the controller has nothing. If you need to access categoriesTreeCtrl.onSelectionChange from child directive, you should not put the onSelectionChange as part of it's $scope, but define it as the controller's property.

controller: function($scope, $element, $attrs){
      this.onSelectionChange = function(category){ ... };
 // $scope.onSelectionChange = function(category){...}
}

Additional :
the categoriesTreeCtrl on the child directive is not equal to $scope.categoriesTreeCtrl, which means, you can't call categoriesTreeCtrl from you template. Look at the ng-change value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top