Reputation: 11
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
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