0

I would like to add a <hr> element between each clone of my transclude function except for the last one clone.

The parent directive have a custom HTML template.
In this template, I call a Attribute directive to transclude the elements.

Sample:

function directiveTransclude() {
    return {
        link: function (scope, element, attr, ctrl, transclude) {
            transclude(function (clone, scope) {
                element.append(clone);
            });
        }
    };
}

This directive help me to manually handle the transclude.
I just have to figure out now how to conditionnally add the <hr>.
I assume to do that I need to add for example element.append('<hr>'); after the first append.

So how could I know how many elements the transclude have to append ?
Is there a $last value or something to tell me that this is the last loop ?

Thanks for the help !

C0ZEN
  • 894
  • 11
  • 41

2 Answers2

0

The controller has been instantiated by the time the link function runs, so I would just keep track of it in a controller attribute.

I'm assuming in the below example that you're passing this directive a collection to iterate over, or at least a count of number of elements you want. I'll also assume that argument is named collection, and that you're using bindToController so that this directive binding is accessible on the controller by this point. Finally, I'm assuming you've also attached an attribute to your controller named iterationCount.

function directiveTransclude() {
    return {
        link: function (scope, element, attr, ctrl, transclude) {
            ctrl.iterationCount++;
            transclude(function (clone, scope) {
                element.append(clone);
                if(ctrl.iterationCount < (ctrl.collection.length - 1)) {
                  element.append('hr');
                }
            });
        }
    };
}

Although, my suggestion would be to do this with css, if <hr> isn't some sort of strange requirement. Using a border and the last-child selector would be MUCH simpler.

Aaron Pool
  • 479
  • 2
  • 6
  • Thanks, I will try this tomorrow. By the way, I tried the CSS way by calling sibling selectors like :last-child on the parent or directly :last-of-type on the child nevertheless that way is not working (children are directives with their own template, so multiple DOM levels here). – C0ZEN Dec 11 '16 at 22:53
  • the `last-of-type` selector is finicky, and the `last-child` selector is actually applied to the child. It means "If I am the last-child". I was also confused by this for quite some time. – Aaron Pool Dec 12 '16 at 17:22
0

Just in case you wonder:

It's late but I just find the solution by using an alternative (with CSS).

As mentioned by @Aaron Pool, I can use last-child selector to achieve that.

the last-of-type selector is finicky, and the last-child selector is actually applied to the child

It's better (faster than DOM injection and safer visually speaking, because <hr> could easily get edited by CSS rules).

I already tried that nevertheless it didn't works as expected.
Despite, today I figure out that my LESS code was that:

&:last-child

Instead of

:last-child

So I was focusing the wrong DOM element, sadly.
I'm happy even if now I feel so dumb.
Greetings and happy new year !

C0ZEN
  • 894
  • 11
  • 41