【问题标题】:AngularJS : Expandable recursive tree tableAngularJS:可扩展的递归树表
【发布时间】:2014-05-06 06:44:12
【问题描述】:

我正在研究角度数据树递归表。所以想法是,抛出树数据(不知道树的部门)并使用可扩展节点将树正确地渲染为表格。现在我通过递归调用模板在表内创建表成功地完成了树表

这里是代码,或者你可以在这里看到它的实际效果:jsfiddle

<script type="text/ng-template"  id="tree_item.html">

   <tr style="width:100%">
      <td><i class="fa fa-folder-open"></i></td>
      <td>
            {{data.name}}

        <div id="expanded-data">
            <table class="table table-striped" id="nested-table">
                    <div ng-repeat="data in data.nodes" ng-include="'tree_item.html'">     </div>
            </table>
        </div>
    </td>
</tr>

</script>


 <table class="table table-striped">
 <thead>
    <tr>
        <th style="width:30px;"><i ng-click="loadItems()" class="fa fa-refresh blueicon"></i></th>
        <th style="width:auto">Data tree</th>
    </tr>
</thead>
<tbody ng-repeat="data in treeData" ng-include="'tree_item.html'">

</tbody>

</table>

现在我坚持下一步,即在您单击文件夹图标时启用切换展开和折叠,然后将子节点设置为 display=none。

我用 ng-switch 尝试了一些,但没有成功。你们有任何想法如何做到这一点?

谢谢你:)

【问题讨论】:

标签: javascript jquery angularjs recursion tree


【解决方案1】:

在此处添加 ng-if

<div id="expanded-data" data-ng-if="childrenVisible">

并为您的树项提供一个属性,该属性定义其子项的可见性。 默认设置属性 true 或 false(如果您想要 false,则默认不添加它)并实现一个 toggleChildren 函数,该函数通过单击 toggleButton(文件夹)调用

scope.toggleChildren = function () {
    scope.item.childrenVisible = !scope.item.childrenVisible;
}

EDIT:// 现在更改文件夹(打开或关闭) http://jsfiddle.net/8f3rL/35/

【讨论】:

    【解决方案2】:

    您可以考虑使用树形网格。

    演示:expandable grid

      <tree-gird tree-data="tree_data"></tree-grid>
    

    提供一个树状结构的数据、列定义和一个您想要扩展的属性。

    提供一个树状结构数据、列定义和一个您想要在控制器中展开的属性。

     $scope.tree_data = [
       {Name:"USA",Area:9826675,Population:318212000,TimeZone:"UTC -5 to -10",
      children:[
        {Name:"California", Area:423970,Population:38340000, TimeZone:"Pacific Time",
            children:[
                {Name:"San Francisco", Area:231,Population:837442,TimeZone:"PST"},
                {Name:"Los Angeles", Area:503,Population:3904657,TimeZone:"PST"}
            ]
        },
        {Name:"Illinois", Area:57914,Population:12882135,TimeZone:"Central Time Zone",
            children:[
                {Name:"Chicago", Area:234,Population:2695598,TimeZone:"CST"}
            ]
         }
       ]
      },    
      {Name:"Texas",Area:268581,Population:26448193,TimeZone:"Mountain"}
    ];
    

    (可选)您可以定义列定义、要在其上使用展开和折叠的属性

    $scope.col_defs = [
       { field: "Description"},
       { field: "DemographicId", displayName: "Demographic Id"},
       { field: "ParentId", displayName: "Parent Id"},
       { field: "Area"},
       { field: "Population"},
       { field: "TimeZone", displayName: "Time Zone"}
    ];
    
    
    $scope.expanding_property = "Name";
    

    详情:https://github.com/khan4019/tree-grid-directive

    【讨论】:

      【解决方案3】:

      使用此表,所有 CRUD 操作和用户友好的缩进:-

      How to display tree data structure using Angularjs-1 and bootstral html table?


      treeDS.html

      <!doctype html>
      <html>
      <head>
          <title>Testbook: Admin App</title>
          <link rel="stylesheet" type="text/css" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
          <style>
      
              .level0{
                  text-indent : 0px;
                  color : #428bca;
              }
              .level1{
                  text-indent : 20px;
                  color : #428bca;
              }
              .level2{
                  text-indent : 40px;
                  color : #428bca;
              }
              .level3{
                  text-indent : 60px;
                  color : #428bca;
              }
              .level4{
                  text-indent : 80px;
                  color : #428bca;
              }
              .level5{
                  text-indent : 100px;
                  color : #428bca;
              }
              .level6{
                  text-indent : 120px;
                  color : #428bca;
              }
              .hasDropdown{
                  color : #428bca ;
              }
              .noDropdown{
                  color : #000000;
              }
      
              div.tooltip-inner {
                  text-align: center;
                  -webkit-border-radius: 0px;
                  -moz-border-radius: 0px;
                  border-radius: 0px;
                  margin-bottom: 6px;
                  background-color: #505050;
                  font-size: 14px;
              }
      
          </style>
      
      </head>
      
      <body  ng-app="treeDataStructureApp" ng-controller="treeDataStructureCtrl">
          <div class="container-fluid" style="padding-left : 25px;">
      
              <br><br><br>
              <div class="row">
                  <div class="col-md-8 col-md-offset-2">
                      <span class="label label-default ng-binding" style="font-size : 25px">
                          Tree Data Structure Implementation Using Bootstrap Table
                      </span>
                  </div>
              </div>
              <br><br><br>
      
              <div class="row">
                  <div class="col-md-3">
                      <button ng-click="addNewNodeAtRootLevel()" type="button" class="btn btn-primary btn-sm">Add New Node</button>
                  </div>
              </div>
      
              <br>
              <div class="row">
                  <div class="col-md-12">
                          <table class="table table-hover table-bordered" id="mytable" style="width: 90%;">
                              <caption></caption>
                              <thead>
                              <tr class="info">
                                  <th
                                  data-toggle="tooltip" data-placement="top" title="click here to expand/close"
                                  ng-click="expandAll()">
                                  Name
      
                                  <span ng-if="!showAll" class="glyphicon glyphicon-triangle-right" 
                                        aria-hidden="true" 
                                        data-toggle="tooltip" data-placement="top" title="Help: expand all nodes">
                                  </span>
      
                                  <span ng-if="showAll" class="glyphicon glyphicon-triangle-bottom" 
                                        aria-hidden="true" 
                                        data-toggle="tooltip" data-placement="top" title="Help: ">
                                  </span>
      
                                  </th>
                                  <th>Id</th>
                                  <th>Operations</th>
                              </tr>
                              </thead>
                              <tbody>
                                  <tr ng-repeat="node in nodesTableArr | filter : {isShow : true }" ng-class=" colorBackgroundOfNewnode(node)" >
                                      <td ng-class="[hasDropdown(node), selectIndentationClass(node)]">
                                          <span ng-model="node.editable" contenteditable='node.isEditable' ng-click="toggleDropdown(node)"> {{node.name}}</span>
                                      </td>
                                      <td contenteditable='false'> {{node.id}} </td>
                                      <td contenteditable='false'>
                                          <span ng-click="addChildNode(node)" class="glyphicon glyphicon-plus" aria-hidden="true"  
                                          data-toggle="tooltip" data-placement="top" title="Help: add new node under this node edit its name and press save button,save button will show after editing its name">    
                                          </span>
      
                                          <span ng-click="deleteNode(node, 'concept')" class="glyphicon glyphicon-minus" 
                                                aria-hidden="true" 
                                                data-toggle="tooltip" data-placement="top" title="Help: delete this node, all nodes under it will also be deleted">
                                          </span>
      
                                          <span ng-click="editNode(node)" class="glyphicon glyphicon-edit" 
                                                aria-hidden="true" 
      
                                                data-toggle="tooltip" data-placement="top" title="Help: edit name and then press update button, update button will show, after editing its name">
                                          </span>
      
                                          <button ng-click="saveNewNodeCB (node, false)" type="button" 
                                                  class="btn btn-primary btn-xs" ng-show="node.isSaveBtn">save
                                          </button>
      
                                          <button ng-click="updateNode(node)" type="button" class="btn btn-primary btn-xs" 
                                                  ng-show="node.isUpdateBtn">update
                                          </button>
      
                                          <span ng-medel="operationStatusMessage" ng-show="node.isShowMessage"> 
                                              <small>{{operationStatusMessage}} </small>
                                          </span>
                                      </td>
                                  </tr>
                              </tbody>
                          </table>
                      </div>
                  </div>
              </div>
      
              <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js" type="text/javascript"></script>
              <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular-route.min.js" type="text/javascript"></script>
              <script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.12.1.js" type="text/javascript"></script>
              <script src="treeDS.js" type="text/javascript"></script>  
      </body>
      


      treeDS.js 文件

      /** * 由 Aditya 于 2015 年 10 月 15 日创建。 */ '使用严格';

      var app = angular.module('treeDataStructureApp',[]); app.controller('treeDataStructureCtrl', ['$scope',function ($scope){

      // add new node at top level here
          $scope.isAddExamNode = false;
          $scope.addNewNodeAtRootLevel = function(){
              $scope.isAddExamNode = true;
              var newNode = {
                          name: "new node",
                          id : "",
                          level: 0,
                          parent: "root",
                          toggleStatus : false,
                          parentId : -1,
                          isShow: true,
                          isEditable : false,
                          childCount: 0,
                          isSaveBtn : false,
                          isShowMessage : false,
                          type : "exam"
                      };
             $scope.nodesTableArr.unshift(newNode);   
          };
      
          // add new node.
          $scope.operationStatusMessage = "";
          $scope.currentNodeSelected = {};
          var uniqueIdForNewNodes = 0;
          $scope.addChildNode = function(node){
              // add row to table.
              $scope.operationStatusMessage = "";
              $scope.currentNodeSelected = node;
              for (var i = 0; i < $scope.nodesTableArr.length; i++) {
                  if($scope.nodesTableArr[i].id == node.id){
                      $scope.nodesTableArr.splice(i + 1, 0, {
                          name: "new node",
                          id : uniqueIdForNewNodes,
                          level: node.level + 1,
                          parent: node.name,
                          toggleStatus : false,
                          parentId : node.id,
                          isShow: true,
                          isEditable : false,
                          childCount: 0,
                          isSaveBtn : false,
                          isShowMessage : false,
                          type : "nonExam"
                      });
                      break;
                  }
              }
      
              uniqueIdForNewNodes += 1;
          };
      
          $scope.saveNewNode = function(node, isExamNode){
              alert("You can send request on server to add this node here.");
              $scope.saveNewNodeCB();
          };
      
          $scope.saveNewNodeCB = function(){
                  $scope.resetOperationStatusMessage();
                  $scope.operationStatusMessage = "node Saved Successfully";
                  $scope.currentNodeSelected.isShowMessage = true;
                  $scope.currentNodeSelected.isSaveBtn = false;
      
                  // update node id in newly added node object, so that if we add new node under it, it has its valid parent id.
                  for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
                      var node = $scope.nodesTableArr[i];
                      if(node == $scope.conceptNodeToAdd)
                          node.id = response.data.node;
                  }
                  alert("send request to server here to save this node.");
          };
      
          $scope.editNode = function(node){
              $scope.nodeNameInOperation = node.name;
              $scope.operationStatusMessage = "";
              $scope.currentNodeSelected = node;
              var nodeName = prompt("Please enter New node Name", node.name);
              if(nodeName != "" && nodeName != null && node.name != undefined && nodeName != node.name){
                node.name = nodeName;
                if(node.id != ""){
                    node.isUpdateBtn = true;
                }
                else{
                    node.isSaveBtn = true;
                }
              }
          };
      
          $scope.updateNode = function(node){
              alert("You can send request on server to update this node.");
              $scope.updateNodeCB();
          };
      
          $scope.updateNodeCB = function(response){                
      
              $scope.resetOperationStatusMessage();
              if(true){
                  $scope.currentNodeSelected.isShowMessage = true;
                  $scope.operationStatusMessage = "node Updated Successfully";
                  $scope.currentNodeSelected.isUpdateBtn = false;
              }
          };
      
          // nodeType = concept/nonConcept
          $scope.nodeToDelete = {};
          $scope.deleteNode = function(node, nodeType){
      
              $scope.nodeNameInOperation = node.name;
              $scope.nodeTypeForMessage = nodeType;
              $scope.nodeToDelete = node;
              $scope.operationStatusMessage = "";
              $scope.currentNodeSelected = node;
              var message;
              if(node.id == ""){
                  for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
                      if($scope.nodesTableArr[i] == $scope.currentNodeSelected)
                          $scope.nodesTableArr.splice(i, 1);
                  }
                  return 0 ;
              }
              var r = confirm("Warning! Be Carefull! On deletion all nodes under this node will be deleted.\nPress ok to delete node");
              if (r == true) {
                  $scope.deleteNodeCB();
                  message = "nodes deleted successfully.";
              } else {
                  message = "process cancelled.";
              }
              $scope.curPageNo = 1;
          };
      
          $scope.deleteNodeCB = function(){
      
            $scope.resetOperationStatusMessage();
            $scope.operationStatusMessage = "node deleted Successfully";
            $scope.currentNodeSelected.isShowMessage = true;
      
            for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
                if($scope.nodesTableArr[i] == $scope.currentNodeSelected)
                    $scope.nodesTableArr.splice(i, 1);
            }
          };
      
          $scope.resetOperationStatusMessage = function(){
              for(var i = 0 ; i < $scope.nodesTableArr.length ; i++){
                  $scope.nodesTableArr[i].isShowMessage = false;
              }
          };
      
          // concept nodes related operations ends here
      
      
          var node = "";
          $scope.nodesTableArr = [];
          $scope.initializeNodeTreeTable = function(pChildArr){
              var length = pChildArr.length || 0;
              for(var i = 0 ; i < length ; i++){ 
      
                  var exam = pChildArr[i];
                  var level = 0;
                  var childCount = 0;
                  if(exam.children && exam.children.length)
                      childCount = exam.children.length;
                  $scope.nodesTableArr.push({name : exam.text, id : exam._id, parent : "root", toggleStatus : false,
                   parentId : -1, isShow : true, isEditable : false, level : 0, childCount : childCount,
                   isSaveBtn : false, isUpdateBtn : false
                      });
                  if(exam.children != undefined)
                  $scope.initializeNodeTreeTableHelper(exam.children, exam.text, exam._id, level);
      
              }
          };
      
          $scope.initializeNodeTreeTableHelper = function(pChildArr, pParentName, pPparentId, pLevel){
              var isShowNode = false;
              pLevel = pLevel + 1 ;
              for(var i = 0 ; i < pChildArr.length ; i++){
                  var node = pChildArr[i];
                  var childCount = node.children != undefined ? node.children.length : 0
                  $scope.nodesTableArr.push({name : node.text, id : node._id, parent : pParentName, toggleStatus : false,
                   parentId : pPparentId, isShow : isShowNode, isEditable : false, level : pLevel, childCount : childCount,
                   isSaveBtn : false, isUpdateBtn : false
                  });
                  if(node.children != undefined)
                      $scope.initializeNodeTreeTableHelper(node.children, node.text, node._id, pLevel)
              }
          };
      
          $scope.selectedExam = "";
          $scope.renderNodeTreeForExam = "selectedExamNode";
          $scope.renderNodeTreeForExam = function(exam){
              $scope.nodesTableArr = [];
              $scope.selectedExam = exam;
              var selectedExamArr = [exam];
              if($scope.selectedExam == "allExams")
                  selectedExamArr = $scope.allExams
              $scope.getAllNodes(selectedExamArr);
          };
      
          // view related functions.
          $scope.selectIndentationClass = function(node){
              return 'level' + node.level;
          };
      
          $scope.hasDropdown = function(node){
              if(node.childCount > 0)
                  return "hasDropdown";
              else
                  return "noDropdown";
          };
      
          $scope.colorBackgroundOfNewNode = function(node){
              if(node.id == ""){
                  return "success";
              }
          };
      
      
          $scope.toggleStatus = false;
          $scope.toggleDropdown = function(node){
              node.toggleStatus = node.toggleStatus == true ? false : true;
              $scope.toggleStatus = node.toggleStatus;
              $scope.toggleDropdownHelper(node.id, $scope.toggleStatus );
          };
      
          $scope.toggleDropdownHelper = function(parentNodeId, toggleStatus ){
              for(var i = 0 ; i < $scope.nodesTableArr.length ; i++) {
                  node = $scope.nodesTableArr[i];
                  if(node.parentId == parentNodeId) {
                      if(toggleStatus == false)
                      $scope.toggleDropdownHelper(node.id, toggleStatus);
                      $scope.nodesTableArr[i].isShow = toggleStatus;
                  }
              }
          };
      
          $scope.showAll = false;
          $scope.expandAll = function(){
              var  i = 0;
              $scope.showAll = $scope.showAll == true ? false : true;
              if($scope.showAll) {
                  for (i = 0; i < $scope.nodesTableArr.length; i++)
                      $scope.nodesTableArr[i]['isShow'] = true;
              }
              else {
                  for (i = 0; i < $scope.nodesTableArr.length; i++)
                      if($scope.nodesTableArr[i]['level'] != 0)
                        $scope.nodesTableArr[i]['isShow'] = false;
              }
          };
      
          $scope.initializeNodeTreeTable(sampleData.data)
      }]);
      
       var sampleData = {
        "data": [
          {
        "_id": "557569e82a39650f65425104",
        "depth": 0,
        "text": "SBI Clerk",
        "exam": "SBI Clerk",
        "children": [
          {
            "_id": "55c2dee72a3965432eaac6a7",
            "depth": 1,
            "text": "Quantitative Aptitude",
            "exam": "SBI Clerk",
            "children": [
              {
                "_id": "55c2dee72a3965432eaac6a8",
                "depth": 2,
                "text": "Simplification",
                "exam": "SBI Clerk",
                "children": [
                  {
                    "_id": "55c2dee72a3965432eaac6a9",
                    "depth": 3,
                    "text": "Bodmas Rule",
                    "exam": "SBI Clerk",
                    "type": "topic",
                    "par": "Bodmas Rule"
                  },
                  {
                    "_id": "55c2dee72a3965432eaac6aa",
                    "depth": 3,
                    "text": "Surds And Indices",
                    "exam": "SBI Clerk",
                    "type": "topic",
                    "par": "Surds And Indices"
                  },
                  {
                    "_id": "55c2dee82a3965432eaac6ab",
                    "depth": 3,
                    "text": "Approx Value",
                    "exam": "SBI Clerk",
                    "type": "topic",
                    "par": "Approx Value"
                  },
                  {
                    "_id": "55c2dee82a3965432eaac6ac",
                    "depth": 3,
                    "text": "Percennodee",
                    "exam": "SBI Clerk",
                    "type": "topic",
                    "par": "Percennodee"
                  }
                ],
                "type": "chapter",
                "par": "Simplification"
              }
            ],
            "type": "subject",
            "par": "Quantitative Aptitude"
          }
        ],
        "type": "exam",
        "par": ""
      }
        ]
      };
      

      jsFiddle:工作示例

      http://jsfiddle.net/Aditya199121/y0te91dm/1/

      【讨论】:

      • 虽然这在理论上可以回答问题,it would be preferable 在这里包含答案的基本部分,并提供链接以供参考。
      • 这个问题只有专门的页面,所以我更愿意给出链接。我们可以包含指向工作示例的链接,其中包含所有代码。
      猜你喜欢
      • 1970-01-01
      • 2020-08-04
      • 2014-07-12
      • 2012-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-02
      相关资源
      最近更新 更多