2

Question: What is the most elegant way to ensure the last separator on each line is never shown?

11|18|3|8|12|1|22|31|61|
11:18:3:8:12:1:22:31:
11,18,3,8,12,61,
1 22 31

Note that the data originates from three different arrays, e.g., the data for line 1 is defined as:

$scope.numbers = [11,18,3,8,12];
$scope.specialNumbers = [1,22,31];
$scope.additionalNumbers = [61];

I would like to see a more elegant/angular way, than just finding the last <li> and remove separator using $element.find, or similar.

I created a little JSFiddle example to demonstrate the problem.

Thanks

4 Answers 4

3

Here is a complete solution, using the proposed $last check (only once) in combination with Array.concat, which is supported in Angular expressions and thus supports bindings. However, to correctly repeat literals, you need to moreover track by $index.

"<li ng-repeat='num in numbers.concat(specialNumbers,additionalNumbers) " +
               "track by $index'>" +
    "<span>{{ num }}</span><span ng-if='!$last'>{{ separator }}</span>" + 
"</li>"
Sign up to request clarification or add additional context in comments.

1 Comment

Btw., if you omit the track by Angular throws an error and tells you to consider using track by. You can (and should always) check the browsers console output in your Fiddles to learn why some code does not work.
2

https://jsfiddle.net/d0ogyfon/

Use Kosta's $last and just concat the lists and iterate once?

    var html = "<ul>" +
                "<li ng-repeat='num in numbers.concat(specialNumbers, additionalNumbers)'>" +
    "<span ng-if='!$last'>{{ num }}{{ separator }}</span>" + 
    "<span ng-if='$last'>{{ num }}</span>" + 
                "</li>" +

           "</ul>";

1 Comment

Nice solution, but unfortunately in that way, bindings will stop to work (when numbers changes, no re-rendering). jsfiddle.net/d0ogyfon/1
2

And, just for fun, how about a CSS-based solution:

Updated Fiddle

CSS:

li.pipe:not(:last-child):after {
    content: '| ';
}
li.colon:not(:last-child):after {
    content: ': ';
}
li.comma:not(:last-child):after {
    content: ', ';
}
li.space:not(:last-child):after {
    content: ' ';
}

HTML:

<div ng-controller="numset1">
    <div test numbers="numbers" special-numbers="specialNumbers" additional-numbers="additionalNumbers" separator-class="pipe"></div>
</div>
<div ng-controller="numset2">
    <div test numbers="numbers" special-numbers="specialNumbers" additional-numbers="additionalNumbers" separator-class="colon"></div>
</div>
<div ng-controller="numset3">
    <div test numbers="numbers" special-numbers="specialNumbers" additional-numbers="additionalNumbers" separator-class="comma"></div>
</div>
<div ng-controller="numset4">
    <div test numbers="numbers" special-numbers="specialNumbers" additional-numbers="additionalNumbers" separator-class="space"></div>
</div>

Directive

app.directive("test",function(){
    var html = 
        "<ul>" +
        "<li class='{{separator}}' ng-repeat='num in numbers'>{{ num }}</li>" +
            "<li class='{{separator}}' ng-repeat='num in specialNumbers'>{{ num }}</li>" +
            "<li class='{{separator}}' ng-repeat='num in additionalNumbers'>{{ num }}</li>" +
        "</ul>";
    
    return {
        template: html,
        scope: {
            separator: "@separatorClass",
            numbers: "=",
            specialNumbers: "=",
            additionalNumbers: "="
        }
    };
});

2 Comments

Looks promising. I think it will not work in IE8, but otherwise I like it (we are still support IE 8).
You're correct. IE8 supports first-child, but not last-child pseudo class selectors. Damn you Microsoft ... ;-)
1

You can make use of $last element:

"<li ng-repeat='num in additionalNumbers'>" +
     "<span ng-if='!$last'>{{ num }}{{ separator }}</span>" + 
     "<span ng-if='$last'>{{ num }}</span>" + 
"</li>"

1 Comment

It will not work with numset2 and numset4 in example.

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.