0

Working on this AngularJs(1.4) code snippet and need help to get recursive tree view to work as desired.

It currently has 4 levels, and what is needed is:

  1. When I open a folder, it should close all folders of same level( including their children and sub-children).

It works for level 2 folders, but not for deeper level 3,4 or even N levels.

Refactoring is also ok using say a Angular Tree view, or something pretty light to achieve same results.

Full Plunker code: https://plnkr.co/edit/vacr1E1sy40mCdSrjW7R?p=preview .

some code:

      onClickFolder: function(paramFolderId) {
        var targetFolderParent = document.getElementById('folder' + paramFolderId) || null;
        var parentFolderWithChild = document.getElementById('parentFolder' + paramFolderId) || null;

        if (parentFolderWithChild !== null) {
          // collapse all children except active
          var allChildNodes = document.querySelectorAll(".child");
          console.log("all child", allChildNodes)
          var childElement = document.getElementById(paramFolderId);
          _fnc.collapseAllChildNodes(allChildNodes, paramFolderId);
          _fnc.toggleTreeView(childElement);
        }

        if (targetFolderParent !== null) {
          var strClass = targetFolderParent.getAttribute('class');
          var selector = "#companyStructureBlock ul i";
          _fnc.removeAllIsOpened(targetFolderParent, selector);
          targetFolderParent.setAttribute('class', strClass + ' isOpened');

        }
      },

      collapseAllChildNodes: function(allChildNodes, paramFolderId) {

        for (i = 0; i < allChildNodes.length; i++) {
          var node = angular.element(allChildNodes[i]);
          console.log("angular node", node, allChildNodes[i])
          if (node.context.id !== "folder" + paramFolderId) {
            node.removeClass("expand-folder");
            node.addClass("collapse-folder");
          } else {
            node.addClass("expand-folder");
          }
        }

      },
      removeAllIsOpened: function(targetFolderParent, selector) {
        //remove all other isOpened class before setting the currentTarget
        var allNodes = document.querySelectorAll(selector);
        for (var i = 0; i < allNodes.length; i++) {
          var node = angular.element(allNodes[i]);
          if (targetFolderParent.dataset.level == angular.element(allNodes[i]).context.dataset.level) {
            node.removeClass('isOpened');
            console.log("here remove all", angular.element(angular.element(node).find("ul .child")).children());
          }
        }
      },
      toggleTreeView: function(childElement) {
        var collapse = angular.element(childElement).hasClass('collapse-folder');
        var expand = angular.element(childElement).hasClass('expand-folder');

        if (!expand && !collapse) {
          angular.element(childElement).addClass("expand-folder");
        } else if (expand & !collapse) {
          angular.element(childElement).removeClass("expand-folder");
          angular.element(childElement).addClass("collapse-folder");
        } else if (!expand & collapse) {
          angular.element(childElement).removeClass("collapse-folder");
          angular.element(childElement).addClass("expand-folder");
        } else if (expand && collapse) {
          angular.element(childElement).removeClass("collapse-folder");
          angular.element(childElement).addClass("expand-folder");
        } else {
          angular.element(childElement).addClass("expand-folder");
        }
      },
    };
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script data-require="lodash.js@*" data-semver="2.4.1" src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
  <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js'></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" />
  <link href="style.css" rel="stylesheet">



</head>

<body ng-controller='Ctrl'>

  <!-- do stuff -->
  <h1>{{title}}</h1>
  <style>
    #companyStructureBlock {
      height: 500px;
      max-width: 259px;
      overflow: auto;
      color: #eee;
      resize: horizontal;
    }
    
    .gridtable tbody tr td {
      padding: 0;
    }
    
    .gridtable tbody tr td .col-sm-12 {
      padding: 0;
    }
    
    .expand-folder {
      display: block;
    }
    
    .collapse-folder {
      display: none;
    }
  </style>

  <div id="companyStructureBlock">

    <div>
      Structures
    </div>
    <br>
    <i id="folder{{structure.folderId}}" ng-class="companyStructure.rootStructure.blnIsOpened? 'isOpened' : '' " class="fas fa-folder folder" src="{{ui.img.companyStructure.folder}}"> <a  ng-click="loadOnDemand($event, companyStructure.rootStructure.folderId,1);filterContactsBasedOnFolder(companyStructure.rootStructure.folderId);"
         class="mrm" ng-bind="companyStructure.rootStructure.levelName | limitTo:20:' ...'"></a></i>
    <ul ng-repeat="structure in structureData | orderBy: ['-unassignedSubstructure','folderId']" id="parentFolder{{structure.folderId}}">
      <i id="folder{{structure.folderId}}" class="fas fa-folder folder" src="{{ui.img.companyStructure.folderplus}}" data-level="{{structure.level}}">
             <a ng-click="loadOnDemand($event,structure.folderId,structure.level);filterContactsBasedOnFolder(structure.folderId);" class="mrm"
             ng-bind="structure.levelName"></a></i>
      <ul id="{{structure.folderId}}" class="child">
      </ul>
    </ul>
    <br>
    <i id="folder{{structure.folderId}}" class="fas">
    <a  ng-click="loadOnDemand($event, companyStructure.rootStructure.folderId,1);filterContactsBasedOnFolder(companyStructure.rootStructure.folderId);"
    class="mrm">Return to All Contacts</a></i>
  </div>



  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.14/angular.min.js"></script>
  <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
  <script src="app.js"></script>
  <script src="factory.js"></script>
  <script src="controller.js"></script>
</body>

</html>

1 Answer 1

0

After looking around, decided to replace the previous implementation using better recursive templates:

Updated plunker: enter link description here

Updated snippet:

    $scope.expand = [];

    $scope.triggerExpand = function(folderId, parentId, level) {

      var i = $scope.expand.indexOf(folderId);
      var ii = $scope.expand.indexOf(parentId);
      if (i >= 0) $scope.expand.length = i;
      else {
        if ($scope.expand.length > level - 2) {
          $scope.expand.length = level - 2;
        }
        $scope.expand.push(folderId);
      }
    
<!DOCTYPE html>
<html ng-app="app">

<head>
  <script data-require="lodash.js@*" data-semver="2.4.1" src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
  <script src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js'></script>
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.1/css/bootstrap.min.css" />
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.8.1/css/all.css" />
  <link href="style.css" rel="stylesheet">



</head>

<body ng-controller='Ctrl'>

  <!-- do stuff -->
  <h1>{{title}}</h1>
  <style>
    #companyStructureBlock {
      height: 500px;
      max-width: 259px;
      overflow: auto;
      color: #eee;
      resize: horizontal;
    }
    
    .gridtable tbody tr td {
      padding: 0;
    }
    
    .gridtable tbody tr td .col-sm-12 {
      padding: 0;
    }
    
    .expand-folder {
      display: block;
    }
    
    .collapse-folder {
      display: none;
    }
    
li > * {
    vertical-align: text-top;
    list-style:none;
}

</style>

  <div id="companyStructureBlock">

    <div>
      Structures
    </div>
    <br>
    
    
    <br>

    <ul>
      <li>

        <i id="folder{{companyStructure.rootStructure.folderId}}" class="fas fa-folder folder isOpened" src="{{ui.img.companyStructure.folderplus}}" data-level="{{structure.level}}">
          <a class="mrm">{{ companyStructure.rootStructure.levelName }}</a></i>

        <ul>
          <li ng-repeat="structure in structureData | filter: { parentFolderId : '' } | orderBy: ['-unassignedSubstructure','folderId']" ng-click="triggerExpand(structure.folderId, structure.parentFolderId, structure.level); $event.stopPropagation();">
            <i id="folder{{structure.folderId}}" class="fas fa-folder folder" src="{{ui.img.companyStructure.folderplus}}" data-level="{{structure.level}}" ng-class="expand.indexOf(structure.folderId) > -1 ? 'isOpened' : '' " >
              <a class="mrm">{{ structure.levelName }}</a></i>
              <div ng-include="'menu'"></div>
          </li>
        </ul>
          

      </li>
    </ul>

    
          
          
    <i id="folder{{structure.folderId}}" class="fas">
    <a  ng-click="loadOnDemand($event, companyStructure.rootStructure.folderId,1);filterContactsBasedOnFolder(companyStructure.rootStructure.folderId);"
    class="mrm">Return to All Contacts</a></i>
  </div>



  <script type="text/ng-template" id="menu">
            <ul ng-show="expand.length > structure.level-2 && expand[structure.level-2] == structure.folderId">
              <li ng-repeat="structure in companyStructure.subStructures | filter: { parentFolderId : structure.folderId } | orderBy: ['folderId']" ng-click="triggerExpand(structure.folderId, structure.parentFolderId, structure.level); filterContactsBasedOnFolder(structure.folderId); $event.stopPropagation();" > 
                <i id="folder{{structure.folderId}}" class="fas fa-folder folder" src="{{ui.img.companyStructure.folderplus}}" data-level="{{structure.level}}" ng-class="expand.indexOf(structure.folderId) > -1 ? 'isOpened' : '' " >
                <a class="mrm">{{ structure.levelName }}</a>
                    <div ng-include="'menu'"></div>
                </i>
              </li>
            </ul>

  </script>



  <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.14/angular.min.js"></script>
  <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.4.js"></script>
  <script src="app.js"></script>
  <script src="factory.js"></script>
  <script src="controller.js"></script>
</body>

</html>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.