Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2. Issue with *ngFor, when i use Pipe

I have a component.

@Component({
    selector: 'top3',
    templateUrl: 'dev/templates/top3.html',
    pipes: [orderBy],
    providers: [HTTP_PROVIDERS, ParticipantService]
})
export class AppTop3Component implements OnInit {

    constructor (private _participantService: ParticipantService) {}

    errorMessage: string;
    participants: any[];

    ngOnInit() {
        this.getParticipants();
    }

    getParticipants() {
        this._participantService.getParticipants()
            .then(
                participants => this.participants = participants,
                error => this.errorMessage = <any>error
            );
    }

}

This component use a service, named _participantService. The _participantService retrieves an array of objects. I output my array of objects in component`s template:

<h2>Top 3</h2>
<table class="table table-bordered table-condensed" cellpadding="0" cellspacing="0">
    <thead>
        <tr>
            <th>#</th>
            <th>Name</th>
            <th>Score</th>
        </tr>
    </thead>
    <tbody>
        <tr *ngFor="#participant of participants | orderBy: '-score'; #i = index">
            <td>{{i+1}}</td>
            <td>{{participant.username}}</td>
            <td>{{participant.score}}</td>
        </tr>
    </tbody>
</table>

I use a Pipe, named orderBy with *ngFor directive. The problem is when I don`t use a Pipe and output array in this way:

<tr *ngFor="#participant of participants; #i = index">

everything is OK, and I've got a correct result:

Correct result

But when I want to sort my object's array and use my Pipe, I don't have any output:

Incorrect result

I`ve got an undefined object in my Pipe function^

@Pipe({
    name: 'orderBy',
    pure: false
})

export class orderBy implements PipeTransform {
    transform(arr: any[], orderFields: string[]): any {
        console.log(arr);
        orderFields.forEach(function(currentField: string) {
            var orderType = 'ASC';

            if (currentField[0] === '-') {
                currentField = currentField.substring(1);
                orderType = 'DESC';
            }

            arr.sort(function(a, b) {
                return (orderType === 'ASC') ? 
                        (a[currentField] < b[currentField]) ? -1 :
                        (a[currentField] === b[currentField]) ? 0 : 1 :                                                                                                                   
                        (a[currentField] < b[currentField]) ? 1 : 
                        (a[currentField] === b[currentField]) ? 0 : -1;
            });

        });
        return arr;
    }
}

enter image description here

like image 551
Edward Avatar asked Dec 01 '25 02:12

Edward


2 Answers

Since you load your data asynchronously using a promise, they are null at the beginning (before the first callback defined in the then method is called).

You need to check if the are parameter is null in your pipe. If so you shouldn't execute the "order by" processing...

When the result will be there, the pipe will be called again with the data (are won't be null). In this case, you will be able to sort data...

You could try this code:

@Pipe({
    name: 'orderBy',
    pure: false
})

export class orderBy implements PipeTransform {
    transform(arr: any[], orderFields: string[]): any {
      if (arr==null) {
        return null;
      }
      (...)
    }
}
like image 98
Thierry Templier Avatar answered Dec 02 '25 18:12

Thierry Templier


According to an example of the doc of the Pipes (https://angular.io/docs/ts/latest/guide/pipes.html#!#jsonpipe), you missed parenthesis :

<tr *ngFor="#participant of (participants | orderBy: '-score'); #i = index">
like image 24
t.ouvre Avatar answered Dec 02 '25 18:12

t.ouvre