1

I am fighting this since a while and as an Angular Noob this drives me crazy.

From my frontend I get a JSON like this:

{
  "LEVEL1": {
    "LEVEL21": {
      "LEVEL31": {
        "VALUE1": null,
        "LEVEL41": {
          "VALUE2": null,
          "VALUE3": null
        },
        "LEVEL42": {
          "VALUE4": null,
          "VALUE5": null
        }
      },
      "LEVEL32": {
        "VALUE6": null,
        "LEVEL51": {
          "VALUE7": null,
          "VALUE8": null
        }
      }
    },
    "LEVEL22": {
      "VALUE9": null,
      "VALUE10": null,
      "VALUE11": null
    }
  }
}

There is no specific order and I have no real figures to count/extract or something similar.

What I like to achieve is to display some kind of tree, so to display every entry (with some intent per 'level') with a + sign to open/display the next level per entry - but only when there is a next level (= value isn't null).

For every entry for which no next level is existing I need to have some 'click' functionality which gives me a concatenated string of the full path, so e.g. something like:

"LEVEL1.LEVEL21.LEVEL42.VALUE5"

So far I tried to resolve this by ng-repeats but as I don't know the depth of the structure I can't hardcode it (and it's superugly as well).

Next thing I tried is some template directive but here I am lost in keeping the scope to have my full string in the end.

Does someone have some inspiration for me?

1 Answer 1

1

You can build a recursive ng-repeat like so:

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

    {{ key }}

    <ul ng-class="{collapse: collapsed, clicky: data !== null}">
      <li ng-repeat="(key, data) in data" 
          ng-include="'tree_item_renderer.html'" 
          ng-init="path = path + (path !== undefined ? '.' : '') + key"
          ng-click="setPath(path); collapsed = !collapsed; $event.stopPropagation();">

      </li>
    </ul>

  </script>

  <li ng-repeat="(key, data) in menuData" 
      ng-include="'tree_item_renderer.html'" 
      ng-click="collapsed = !collapsed; $event.stopPropagation();"></li>

Controller:

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {

  $scope.setPath = function(path) {
    alert(path);
  };

  $scope.menuData = {
    "LEVEL1": {
      "LEVEL21": {
        "LEVEL31": {
          "VALUE1": null,
          "LEVEL41": {
            "VALUE2": null,
            "VALUE3": null
          },
          "LEVEL42": {
            "VALUE4": null,
            "VALUE5": null
          }
        },
        "LEVEL32": {
          "VALUE6": null,
          "LEVEL51": {
            "VALUE7": null,
            "VALUE8": null
          }
        }
      },
      "LEVEL22": {
        "VALUE9": null,
        "VALUE10": null,
        "VALUE11": null
      }
    }
  };
});

Here is a working plunker example.

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

2 Comments

Thank you very much! I exactly tried this as well - but what I am struggling with is how to get the concatenated string in the end. So when I click on a leaf it should provide me with the path to it. So e.g. when I click on VALUE4 I need a string in my controller looking like: LEVEL1.LEVEL21.LEVEL31.LEVEL42.VALUE4 - especially as VALUE4 may occur several times - so I can't search it later on.
See my updated answer. It's probably not a great idea to build the path in the view -- but it shows you a way to do it.

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.