0
votes

Given an Angular directive with the following DOM API:

<my-tree>
  <my-tree-item>First</my-tree-item>
  <my-tree-item>Second</my-tree-item>
  <my-tree-item>Third</my-tree-item>

  <my-tree-group>
    A group

    <my-tree-item>Forth</my-tree-item>
    <my-tree-item>Fifth</my-tree-item>
    <my-tree-item>Sixth</my-tree-item> 
  </my-tree-group>
</my-tree>

How can I create something like this with a template and the following data structure:

[
        {
            name: 'First'
        },
        {
            name: 'Second'
        },
        {
            name: 'Third'
        },
        {
            name: 'A group',
            children: [
                {
                    name: 'Forth'
                },
                {
                    name: 'Fifth'
                },
                {
                    name: 'Sixth'
                }
            ]
        }
    ]

The real data structure may continue down to any depth.

ng-repeat and ng-switch seem needed but require or leave behind extra DOM nodes. For example what should ng-repeat be put on since the item can be 1 of 2 types. When using ng-switch it seemed to help by using it as an element, but that leaves a ng-switch in the DOM.

I considered merging my-tree-item and my-tree-group, but having separate directives seems to make sense as my-tree-group would have extra options that don't apply to regular items.

Is there a way to use Angular to create this exact structure without extra nodes?

Is there a better way to deal with this?

1
What problems do the extra nodes cause? - Matt Way
can use replace:true in directive so no extra nodes exist - charlietfl
@MattWay these directives target an existing code base. Extra nodes break certain assumptions that the code is making about the DOM structure, which breaks functionality and styling. - corsen
@charlietfl replace:true does not get rid of the extra nodes created by ng-switch or help get rid of the extra wrapper needed for a ng-repeat target. - corsen
then don't use ng-switch and it sounds like you need to change how ng-repeat is being used. We don't know what your markup expectations are and if you really want to get this resolved would be best to provide plunker demo that others can help modify - charlietfl

1 Answers

0
votes

What you need to do is create a directive to deal with your required hierarchy. You pass your json object to the directive via an attribute <div my-tree="somejsonobj"></div>, and then have the directive build your required DOM.

Have the directive loop through the current level of the JSON hierarchy, and create the appropriate nodes. If the current item has children (based on your above schema), then create a DOM node that is itself a new instance of your directive, but passing in the current item with children as the root.

Obviously this would be much simpler if you were ok with the extra nodes ng-repeat creates, as you would not need any custom directives.

Here is a quick example post I found on tree like directives: http://blog.stackfull.com/2014/02/trees-in-angularjs/