Asked  6 Months ago    Answers:  5   Viewed   49 times

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
    • example 1 [stackoverflow]
    • example 2 [angular jsfiddles page]
  • don't use a directive at all, but a <script> template which refers to itself
    • example 1 [google groups]

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)?



Inspired by the solutions described in the thread mentioned by @dnc253, I abstracted the recursion functionality into a service.

module.factory('RecursionHelper', ['$compile', function($compile){
    return {
         * Manually compiles the element, fixing the recursion loop.
         * @param element
         * @param [link] A post-link function, or an object with function(s) registered via pre and post properties.
         * @returns An object containing the linking functions.
        compile: function(element, link){
            // Normalize the link parameter
                link = { post: link };

            // Break the recursion loop by removing the contents
            var contents = element.contents().remove();
            var compiledContents;
            return {
                pre: (link && link.pre) ? link.pre : null,
                 * Compiles and re-adds the contents
                post: function(scope, element){
                    // Compile the contents
                        compiledContents = $compile(contents);
                    // Re-add the compiled contents to the element
                    compiledContents(scope, function(clone){

                    // Call the post-linking function, if any
                    if(link &&{
              , arguments);

Which is used as follows:

module.directive("tree", ["RecursionHelper", function(RecursionHelper) {
    return {
        restrict: "E",
        scope: {family: '='},
            '<p>{{ }}</p>'+
            '<ul>' + 
                '<li ng-repeat="child in family.children">' + 
                    '<tree family="child"></tree>' +
                '</li>' +
        compile: function(element) {
            // Use the compile function from the RecursionHelper,
            // And return the linking function(s) which it returns
            return RecursionHelper.compile(element);

See this Plunker for a demo. I like this solution best because:

  1. You don't need an special directive which makes your html less clean.
  2. The recursion logic is abstracted away into the RecursionHelper service, so you keep your directives clean.

Update: As of Angular 1.5.x, no more tricks are required, but works only with template, not with templateUrl

Tuesday, June 1, 2021
answered 6 Months ago

This isn't possible with [innerHTML]="..." at all.
You can compile components at runtime to get components and directives for dynamic HTML.

See How can I use/create dynamic template to compile dynamic Component with Angular 2.0? for more details.

Tuesday, July 6, 2021
answered 5 Months ago

The problem arises because within your loop, this gets redefined to the inner function scope.

countChildren(n, levelWidth, level) {
    var self = this; // Get a reference to your object.

    if (n.children && n.children.length > 0) {
        if (levelWidth.length <= level + 1) {
        levelWidth[level + 1] += n.children.length;

        n.children.forEach(function (n) {
            // Use "self" instead of "this" to avoid the change in scope.
            self.countChildren(n, levelWidth, level+1);
    // Return largest openend width
    return levelWidth;
Wednesday, August 11, 2021
answered 4 Months ago

Expressions in Angular2 are very similar to expressions in Angular in terms of the scope of what they allow.

JavaScript expressions that promote side effects are prohibited including

  • Assignment (= +=, -=)
  • Using the new keyword
  • Chaining expressions using a semicolon or comma
  • Increment (++) and decrement operators

Furthermore, there is no support for bitwise operators like | or &

Generally, it's a good idea to put complex JavaScript logic inside a controller or component, instead of inside a view. This is because of the Separation of Concerns design principle and making code more modular and readable.!#template-expressions

Tuesday, August 24, 2021
answered 3 Months ago

i+1 means "return value that is one larger than i, don't change i"

i++ means "increment i by one, but return the original value"

++i means "increment i by one and return the incremented value"

So in this case if you use i+1 you're not changing the value of i, but you're sending a value one larger than i as an argument. You could also use the ++i, if you would need the value in i to change also.


i = 10
a = i+1
// a = 11, i = 10

i = 10
a = i++
// a = 10, i = 11

i = 10
a = ++i
// a = 11, i = 11

The same applies also for i-1, i-- and --i

Friday, November 5, 2021
Mike Schall
answered 3 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :