Tuesday, April 19, 2016

How make a nested or “tree” table/list in AngularJS

Leave a Comment

I'm new to AngularJS (and web development) but quite excited about the two-way binding and ng-repeat possibilities.

I would like to build a table like structure of textfields where i can add more fields to a column and then it adds fields to the columns at the right. Wish to use it to build a nested JSON file.

enter image description here

Currently thinking of an json structure like this, but would like to have a more flat structure instead...

{   "NoClicks":      { "C1": ["R1"],       "C2": ["R1"],       "C3": ["R1"]     },   "C1_R1_clicked":     { "C1": ["R1", "R2"],       "C2": ["R1", "R2"],       "C3": ["R1", "R2"]     },   "C2_R1_clicked":     { "C1": ["R1"],       "C2": ["R1", "R2"],       "C3": ["R1", "R2"]     }     ,   "C3_R1_clicked":     { "C1": ["R1"],       "C2": ["R1"],       "C3": ["R1", "R2"]     } } 

Update

I have tried to answer my own question and are getting very close to the target..

But I would be thankful for any answer (or mod of my answer) that lets me archive the goal. This will of course marked as the solution to the question.

3 Answers

Answers 1

Combinding this stackoverflow question Display nested list like a table with AngryCat's Amazing JSFiddle of nested nodes seems to get me half of the way

Becomes this: JSFiddle

HTML

<script type="text/ng-template" id="my-tmpl">   {{data.name}}   <button class="btn" ng-click="add(data)" ng-show="levelLimit(data)">     Add node </button>    <button class="btn" ng-click="delete(data)" ng-show="hasNodes(data)">     Delete nodes </button>    <ul>     <li ng-repeat="data in data.nodes" ng-include="'my-tmpl'"></li>   </ul> </script>  <ul ng-controller="TreeController">   <li ng-repeat="data in tree" ng-include="'my-tmpl'"></li> </ul> 

JS

    angular.module("myApp", [])   .controller("TreeController", function($scope) {     var levelLimit = function(data) {       if (data.level < 3) {         return true;       } else {         return false;       };     };      var addNode = function(data) {       var post = data.nodes.length + 1;       var newName = data.name + '-' + post;       var newLevel = data.level + 1;       if (levelLimit(data)) {         var node = {           name: newName,           nodes: [],           level: newLevel         };         data.nodes.push(node);         addNode(node);       }     };      $scope.tree = [{       name: "Node",       nodes: [],       level: 1     }];      $scope.hasNodes = function(data) {       return (data.nodes.length > 0)     };      $scope.levelLimit = levelLimit;      $scope.delete = function(data) {       data.nodes = [];     };      $scope.add = addNode;   }); 

CSS

li {   display: inline-flex;   border: 1px solid #000;   padding: 0px;   list-style: none; } li li {   display:flex; } 

I just need to figure out 3 parts

  1. Call the add() first time it loads
  2. Move the add and delete buttons to the right (but still having the same function)
  3. Be able to add major rows.. Or somehow get the first list level to be a header...?

Answers 2

Since the columns are saved as object properties you need to apply the following syntax for the first ng-repeat:

<div ng-repeat="(key, value) in myObj"> ... </div>

The valuevariable will contain your column array. You can iterate through the array with the deault syntax.

Answers 3

Hmm I'm a lil' confused about the setup, but it sounds as though you would want something functioning as a recursive directive ? So perhaps:

app.directive('jsonObjectView',[function(){    return {      restrict: 'E',      scope: {        jsonObjectView: '=' // two-way bind about the directive's name      },      template: '<div ng-repeat="(property,object) in JSONObjects"><div class="object-container"><json-object-view="object"></json-object-view><button ng-click="addProperty(object)"></button></div></div>', // the html template      compile: function (element,attributes){        // craft your "addProperty" function (not sure if you want a pop-up or how you're going about it)        return {          post: function postLink(scope,elem,attr,ctrl){            // Anything else you ought to do          }        };      }    };  }])
<json-object-view="object"></json-object-view>    <!-- Which would equate to: -->    <div ng-repeat="(property,object) in JSONObjects">    <div class="object-container">      <json-object-view="object"></json-object-view>      <button ng-click="addProperty(object)"></button>    </div>  </div>

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment