12

Trying to learn something about filtering and ordering in Angular 2. I can't seem to find any decent resources and I'm stuck at how to order an ngFor output in reverse order using the index. I have written the the following pipe put it keeps giving me errors that array slice in not a function.

@Pipe({
    name: 'reverse'
})
export class ReversePipe implements PipeTransform {
    transform(arr) {
        var copy = arr.slice();
        return copy.reverse();
    }
}

and my ngfor looks like this.

<div class="table-row generic" *ngFor="let advert of activeAdverts | reverse let i = index;" [attr.data-index]="i" (click)="viewAd(advert.title)">      
    <div class="table-cell white-text">{{ i+1 }}</div>                    
    <div class="table-cell white-text">{{advert.title}}</div>
    <div class="table-cell green-text">{{advert.advert}}</div>
</div>
Shadow
  • 7,997
  • 4
  • 45
  • 55
Hamburgersn Heroin
  • 197
  • 1
  • 1
  • 12

7 Answers7

13

I would add .slice() as well

*ngFor="let advert of activeAdverts.slice().reverse() let i = index;"
msanford
  • 11,125
  • 10
  • 64
  • 87
Chris Skura
  • 161
  • 1
  • 3
  • 1
    Why to use slice() here? And if we will not do slice() what will happen? – Satish Patro Feb 11 '19 at 05:22
  • 2
    Reverse() works in place. It means, it will change the original array. Slice without parameters returns a copy of activeAdverts, so original array, in this case, stays unchanged. – Prokhor Sednev Apr 26 '19 at 12:39
11

For such common use cases, I would suggest you to use reverse pipe from ng-pipes module: https://github.com/danrevah/ng-pipes#reverse-1

From the DOCS:

in the controller:

this.items = [1, 2, 3];

in the view:

<li *ngFor="let item of items | reverse"> <!-- Array: [3, 2, 1] -->
D_R
  • 4,738
  • 3
  • 43
  • 62
6

I think @BhaskerYadav gave the best answer. Changing the original array is a bad idea and his/her idea has no side-effects, performance or otherwise. IMHO it just needs a slight improvement as all that index dereferencing is unreadable at scale.

<tr *ngFor="let _ of activeAdverts; let i = index">
  <ng-container *ngIf="activeAdverts[activeAdverts.length-i-1] as advert">
    <td>{{advert.p}}</td>
    <td>{{advert.q}}</td>
    ...
  </ng-container>
</tr>
Mark Florence
  • 343
  • 4
  • 8
  • This worked for me. But, didn't understand what you mean by "index dereferencing is unreadable at scale". Could you please help explain. Thanks. – User3250 Aug 07 '18 at 16:07
  • Sure thing. All the examples show just a couple of table cells. But that isn't realistic. What if there were 10, 20? If you had to write `activeAdverts[activeAdverts.length-i-1]` in each, your template would rapidly become unreadable. The `as` keyword of `*ngIf` is underused but great for creating a local variable -- and assigning it with the `*ngIf` expression. So in my example, you only need write the lengthy index dereference once. – Mark Florence Aug 08 '18 at 18:46
  • Ahh! Got you. Thanks a ton! :) – User3250 Aug 09 '18 at 01:38
  • @MarkFlorence what if then I dynamically push activeAdverts? – Chirag Jan 16 '19 at 06:43
4

Using the following method u can reverse the output, but orignal array won't be modified,

 <tr *ngFor="let advert of activeAdverts; let i = index" >
           <td>{{activeAdverts[activeAdverts.length-i-1]}}</td>
  </tr>
BhaskerYadav
  • 559
  • 3
  • 22
2

The most simple way I was able to make it work is to just use activeAdverts.reverse(). In your case:

<div class="table-row generic" *ngFor="let advert of activeAdverts.reverse() let i = index;" [attr.data-index]="i" (click)="viewAd(advert.title)">      
    <div class="table-cell white-text">{{ i+1 }}</div>                    
    <div class="table-cell white-text">{{advert.title}}</div>
    <div class="table-cell green-text">{{advert.advert}}</div>
</div>

I found this answer to do the trick

Pini Cheyni
  • 4,496
  • 2
  • 37
  • 52
1

Use this

*ngFor="let item of items.slice().reverse()"
matthias_h
  • 11,260
  • 9
  • 20
  • 39
Trilok Singh
  • 979
  • 10
  • 7
0

Lodash reverse worked for me.

import { reverse} from "lodash";

this.cloudMessages = reverse(this.cloudMessages)
Sampath
  • 58,546
  • 53
  • 279
  • 406