0

i have 2 directives that create a grid table. For each row we may have some actions and my question is can i access in some way those actions without calling $parent.$parent.action in my template?

            .directive("grid", function ($compile, $parse) {
            return {
                restrict: 'AE',
                scope:  {
                    templateUrl         : '@?',
                    columns             : '=',
                    filterBy            : '=?',
                    excludeSortColumns  : '=?'
                },
                controller: GridController,
                controllerAs: 'grid',
                bindToController: true,
                replace: true,
                transclude: true,
                templateUrl: function($element, $attrs) {
                    if(!angular.isDefined($attrs.filterBy)) {
                        return '/assets/js/src/templates/partials/grid/grid-sortable.tpl.html';
                    }
                    return $attrs.templateUrl || '/assets/js/src/templates/partials/grid/grid.tpl.html';
                },
                link: function($scope, $element, $attrs, ctrl, transclude) {
                    //filter collection when user has typed some letter
                    $element.on('keyup', function() {
                        $scope.$apply(function() {
                            $scope.$parent.filterValue = $('.filterBy').val();
                        });
                    });
                    //var e = $compile(transclude())($scope.$parent);
                    //angular.element('.table').append(e);
                    $element.append(transclude($scope.$parent));
                }
            };

            function GridController($scope, $element, $attrs) {
                var vm = this;

                vm.columns = $parse($attrs.columns)($scope.$parent);
                vm.excludeSortColumns = angular.isDefined($attrs.excludeSortColumns) ? $parse($attrs.excludeSortColumns)($scope.$parent) : false;
                vm.filterCol = angular.isDefined($attrs.filterBy) ? $parse($attrs.filterBy)($scope.$parent) : false;

                vm.sortBy = function(column) {
                    if(!vm.isExludedSortBy(column)) {
                        vm.predicate = column;
                        vm.reverse = (vm.predicate === column) ? !vm.reverse : false;
                        var sortType = (vm.reverse) ? '-' : '+';
                        $scope.$parent.orderByColumn = sortType + column;
                    }
                };

                vm.isExludedSortBy = function(column) {
                    if(!vm.excludeSortColumns) {
                        return true;
                    }
                    if(vm.excludeSortColumns.indexOf(column) >= 0) {
                        return true;
                    }
                    return false;
                };
            };
        })

        .directive("gridBody", function ($parse) {
            return {
                restrict: 'AE',
                scope:  {
                    templateUrl         : '@?',
                    collection          : '='
                },
                require: '^grid',
                controller: function($scope, $element, $attrs) {
                    var vm = this;
                    vm.collection = $parse($attrs.collection)($scope.$parent);
                },
                controllerAs: 'body',
                bindToController: true,
                replace: true,
                transclude: false,
                templateUrl: function($element, $attrs) {
                    return $attrs.templateUrl || '/assets/js/src/templates/partials/grid/grid-body.tpl.html';
                }
            };
        })

This is a template:

<tbody>
    <tr ng-repeat="item in body.collection | gridFilterBy:$parent.filterBy:$parent.filterValue | orderBy:$parent.orderByColumn track by $index">
        <td class="col-sm-1">{{item.id}}</td>
        <td class="col-sm-2">{{item.name}}</td>
        <td class="col-sm-1">{{item.latest_result.count}}</td>
        <td class="col-sm-2">{{item.created_at}}</td>
        <td class="col-sm-2">{{item.updated_at}}</td>
        <td class="col-sm-4">
            <button class="btn btn-primary" ng-disabled="item.has_cluster" role="button" ng-click="$parent.$parent.addCluster(item.id)">
                Crea cluster
            </button>
            <button class="btn btn-primary" role="button" ng-click="$parent.getExports(item.id, item.name)">
                Export
            </button>
            <button class="btn btn-primary" role="button" ng-click="$parent.$parent.loadQuery(item.id)">
                Visualizza
            </button>
            <button class="btn btn-primary" role="button" ng-click="$parent.$parent.removeQuery(item.id)">
                Rimuovi
            </button>
        </td>
    </tr>
</tbody>
            <grid columns="columns" filter-by="filterBy" exclude-sort-columns="excludeColumns">
            <grid-body collection="result.items" template-url="/assets/js/src/templates/partials/grid/grid-body.tpl.html"></grid-body>
        </grid>

i can't get grid controller

Thanks for all replies.

1 Answers1

0

Typically this is done through the directive controllers. The following is an example of setting up parent and child directive controllers to be aware of each other:

app.directive('parentDir', function() {
  return {
    restrict: 'A',
    controller: function($scope, $element, $attrs) {
      this.parentInit = function(ctrl) {
        console.log(ctrl);
      };

      this.parentClick = function(param) {

      };
    },
    link: function(scope, element, attrs) {

    }
  }
});

app.directive('childDir', function() {
  return {
    restrict: 'A',
    require: ['childDir', '^parentDir'],
    controller: function($scope, $element, $attrs) {
      var parentCtrl;
      this.childInit = function(parentCtrl) {
        console.log(parentCtrl);
        parentCtrl = ctrl;
      };

      $scope.childClick = function(param) {
        parentCtrl.parentClick(param);
      };
    },
    link: function(scope, element, attrs, ctrls) {
      ctrls[0].childInit(ctrls[1]);
      ctrls[1].parentInit(ctrls[0]);
    }
  }
});

Here is a plunk with a demo.

Rob J
  • 6,609
  • 5
  • 28
  • 29
  • Ok i know that i can use require attribute to retrieve parent controller but when i set it on my child directive it throws this error:`Controller 'grid', required by directive 'gridBody', can't be found!` – Oskar Marciniak Feb 11 '16 at 09:00