John
John

Reputation: 11

Angular 2 how to filter object in view

I have a problem to filter object in my view. My aim is to load a tasks list from a simple webservice (tasks just have a name and a status (todo/done)).

When I don't use webservice and the data are hardcoded in my service i manage to filter my results with a custom Pipe like this

transform(value, args) {
    if (args[0] === true)
        return value.filter((item) => item.status == 'done');
    return value.filter((item) => item.status == 'todo');
}

and the view is like this

<ul class="list-group">
<li  class="list-group-item" *ngFor="#task of tasks | done: false">
    <button  class="btn btn-default btn-xs pull-right" (click)="task.setStatus('done')" *ngIf="(task.status == 'todo')">Done</button>
    {{ task.name }}
</li>

But since i'm loading data from external source, I can't make my custom pipe working, value is undefined probably because of asynchronous datas.

Here the component loading datas :

export class TaskComponent implements OnInit {
task = new Task();
public tasks: Task[];

constructor(public _taskService: TaskService) { }

getTasks() {
    this._taskService.getWsTask().subscribe(tasks => this.tasks = tasks);
}

ngOnInit() {
    this.getTasks();
}

and the associated service

export class TaskService {
tasks: Task[];

constructor(public http: Http) {
    console.log('Task Service created.');
}

public getWsTask(){
    return this.http.get('http://localhost:3000/tasks')
        .map((responseData) => responseData.json())
        .map((tasks: Array<any>) => {
            let result: Array<Task> = [];
            if (tasks) {
                tasks.forEach((task) => {
                    result.push(
                        new Task(task.name, task.status));
                });
            }
            return result;
        });
        ;
}

You can find my service class and components here : enter link description here

Thanks for any kind of help

Upvotes: 1

Views: 1171

Answers (1)

Thierry Templier
Thierry Templier

Reputation: 202156

You need to check that the value isn't null in your filter. As a matter of fact the value parameter is null at first. When the list is received from the HTTP request, the filter will be called again with this value.

transform(value, args) {
  if (value != null) {
    if (args[0] === true) {
      return value.filter((item) => item.status == 'done');
    }
    return value.filter((item) => item.status == 'todo');
  }
}

As suggested by Eric, you could also leverage the async pipe instead of calling directly the subscribe function on your observable:

getTasks() {
  this.tasks = this._taskService.getWsTask();
}

Your template needs to be refactored this way:

<ul class="list-group">
  <li class="list-group-item" *ngFor="#task of (tasks | async | done: false)">
    <button class="btn btn-default btn-xs pull-right"
            (click)="task.setStatus('done')"
            *ngIf="(task.status == 'todo')">Done</button>
      {{ task.name }}
  </li>
</ul>

Hope it helps you, Thierry

Upvotes: 1

Related Questions