2

I'm trying to write an AngularJs directive that will recursively nest UI Bootstrap accordion in a tree like structure.

I've been trying to apply the recipe found here: Recursion in Angular directives, specifically this one...

I've had some success... with a few problems I can't figure out.

Here's my result.

  1. There's an obvious problem where my headers are only displayed for the "leaf" items.

  2. For adding the child elements inside of the accordion-group, I used $element.find("p").replaceWith(childItem); but I'm thinking there must be a more elegant way.

Community
  • 1
  • 1
ddx001
  • 2,575
  • 1
  • 17
  • 13

3 Answers3

2

I got it to work based on the other example in the Reference question (yeah, should have dug deeper...)

Fixed!!!

Community
  • 1
  • 1
ddx001
  • 2,575
  • 1
  • 17
  • 13
0

Here is the Plunker preserved, with a rough, but working, enhancement that decouples the name of the child elements and heading field from deep within the directive (see "kids" and "childs" $scope variables) so this directive can be used on any data set.

function Node(name, children) {
    this.name = name;
    this.children = children || [];
}

angular.module('myApp', ['ui.bootstrap'])

.directive('nodeList', function($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: {
            nodes: '=ngModel',
            kids: '@',
            headingField: '@'
        },
        link: function ($scope, $element, $attrs) {
            if (angular.isArray($scope.nodes)) {
                $element.append('<accordion close-others="true"><node ng-repeat="item in nodes" ng-model="item" childs="{{kids}}" heading-field="{{headingField}}"></node></accordion>');
            } 
            $compile($element.contents())($scope.$new());
        }
    };
})

.directive('node', function($compile) {
    return {
        restrict: 'E',
        terminal: true,
        scope: {
            node: '=ngModel',
            childs: '@',
            headingField: '@'
        },
        link: function ($scope, $element, $attrs) {
            if (angular.isArray($scope.node[$scope.childs]) && $scope.node[$scope.childs].length > 0) {
                $element.append('<accordion-group><accordion-heading>{{node[headingField]}}</accordion-heading><node-list ng-model="node[childs]" kids="{{childs}}" heading-field="{{headingField}}"></node-list></accordion-group>');
            } else {
                $element.append('<accordion-group><accordion-heading>{{node[headingField]}}</accordion-heading></accordion-group>');
            }
            $compile($element.contents())($scope.$new());
        }
    };
})

.controller('myView', function($scope) {
  $scope.data = [
    new Node('Group 1', [
        new Node('Sub 1.1', [
            new Node('Sub 1.1.1', [
                new Node('Child 1.1.1.1'),
                new Node('Child 1.1.1.2')]),
            new Node('Sub 1.1.2', [
                new Node('Child 1.1.2.1'),
                new Node('Child 1.1.2.2'),
                new Node('Child 1.1.2.3')])]),
        new Node('Sub 1.2', [
            new Node('Child 1.2.1'),
            new Node('Child 1.2.2')])]),
    new Node('Group 2', [
        new Node('Sub 2.1', [
            new Node('Child 2.1.1')])])];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<!doctype html>
<html ng-app="myApp">
  <head>
    <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.10.0.js"></script>
    <link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
  </head>
  <body>

    <div ng-controller="myView">
      <h1>Test</h1>
      <node-list ng-model="data" kids="children" heading-field="name"></node-list>
    </div>
  </body>
</html>
lukkea
  • 3,606
  • 2
  • 37
  • 51
0

For newer versions of UI Bootstrap

I can't comment yet but I wanted to add that the plunkr from @user280767 works for the version of ui.bootstrap they are using. For me, I had to replace the accordion* elements in the directive with the new format uib-accordion* listed in their documentation. Hope this helps users!