There are a couple of popular recursive angular directive Q&A's out there, which all come down to one of the following solutions:
- manually incrementally 'compile' HTML based on runtime scope state
- don't use a directive at all, but a <script> template which refers to itself
The first one has the problem that you can't remove previously compiled code unless you comprehensibly manage the manual compile process. The second approach has the problem of... not being a directive and missing out on its powerful capabilities, but more urgently, it can't be parameterised the same way a directive can be; it's simply bound to a new controller instance.
I've been playing with manually doing an angular.bootstrap
or @compile()
in the link function, but that leaves me with the problem of manually keeping track of elements to remove and add.
Is there a good way to have a parameterized recursive pattern that manages adding/removing elements to reflect runtime state? That is to say, a tree with a add/delete node button and some input field whose value is passed down a node's child nodes. Perhaps a combination of the second approach with chained scopes (but I have no idea how to do this)?
I don't know for sure if this solution is found in one of the examples you linked or the same basic concept, but I had a need of a recursive directive, and I found a great, easy solution.
You should create the
recursive
directive and then wrap it around the element that makes the recursive call.There is a really really simple workaround for this that does not require directives at all.
Well, in that sense, maybe it is not even a solution of the original problem if you assume you need directives, but it IS a solution if you want a recursive GUI structure with parametrized sub-structures of the GUI. Which is probably what you want.
The solution is based on just using ng-controller, ng-init and ng-include. Just do it as follows, assume that your controller is called "MyController", your template is located in myTemplate.html and that you have an initialization function on your controller called init that takes argument A, B, and C, making it possible to parametrize your controller. Then the solution is as follows:
myTemplate.htlm:
I found by plain conincidence that this kind of structure can be made recursive as you like in plain vanilla angular. Just follow this design pattern and you can use recursive UI-structures without any advanced compilation tinkering etc.
Inside your controller:
The only downside I can see is the clunky syntax you have to put up with.
As of Angular 1.5.x, no more tricks are required, the following has been made possible. No more need for dirty work arounds!
This discovery was a by product of my hunt for a better/cleaner solution for a recursive directive. You can find it here https://jsfiddle.net/cattails27/5j5au76c/. It supports as far is 1.3.x.
Now that Angular 2.0 is out in preview I think it's ok to add an Angular 2.0 alternative into the mix. At least it will benefit people later:
The key concept is to build a recursive template with a self reference:
You then bind a tree object to the template and watch the recursion take care of the rest. Here is a full example: http://www.syntaxsuccess.com/viewarticle/recursive-treeview-in-angular-2.0
I ended up creating a set of basic directives for recursion.
IMO It is far more basic than the solution found here, and just as flexible if not more, so we are not bound to using UL/LI structures etc... But obviously those make sense to use, however the directives are unaware of this fact...
A Super simple example would be:
The implementation of 'dx-start-with' an 'dx-connect' is found at: https://github.com/dotJEM/angular-tree
This means you don't have to create 8 directives if you need 8 different layouts.
To create a tree-view on top of that where you can add or delete nodes would then be rather simple. As in: http://codepen.io/anon/pen/BjXGbY?editors=1010
From this point on, the controller and template could be wrapped in it's own directive if one would wish for it.
Inspired by the solutions described in the thread mentioned by @dnc253, I abstracted the recursion functionality into a service.
Which is used as follows:
See this Plunker for a demo. I like this solution best because:
Update: As of Angular 1.5.x, no more tricks are required, but works only with template, not with templateUrl