Angular 2 Http Observable 和 Pipe 的使用
Angular 2 Usage of Http Observable and Pipe
我有一个调用 REST 端点的服务:
import { Task } from './task';
import { TaskStatus } from './task-status';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class TaskService {
constructor(private http: Http){
}
getTasks() {
return this.http.get('http://localhost:8080/tasks').map(res => res.json()).map(rest => rest._embedded.tasks);
}
}
端点returns结果如下:
{
"_embedded": {
"tasks": [
{
"title": "zxc",
"description": "zxc",
"status": "New",
"_links": {
"self": {
"href": "http://localhost:8080/tasks/1"
},
"task": {
"href": "http://localhost:8080/tasks/1"
}
}
},
{
"title": "asd",
"description": "qweqwe",
"status": "New",
"_links": {
"self": {
"href": "http://localhost:8080/tasks/2"
},
"task": {
"href": "http://localhost:8080/tasks/2"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/tasks"
},
"profile": {
"href": "http://localhost:8080/profile/tasks"
}
},
"page": {
"size": 20,
"totalElements": 3,
"totalPages": 1,
"number": 0
}
}
我在这个组件中使用服务:
@Component({
selector: 'app-mycomp',
templateUrl: './my.component.html',
styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {
tasks: Array<Task>;
constructor(private taskService:TaskService) {
taskService.getTasks()
.subscribe(tasks => this.tasks = tasks,
err => console.error(err),
() => console.log('done'));
}
}
模板看起来像这样;
<task-details *ngFor="let task of tasks" [task]="task"></task-details>
这按预期工作,但是当我尝试在模板中使用管道时:
<task-details *ngFor="let task of tasks | WithStatus: TaskStatus.New" [task]="task"></task-details>
我收到错误 "Cannot read property 'filter' of undefined"。
管道实现如下:
import { Pipe, PipeTransform } from '@angular/core';
import { TaskStatus } from './task-status';
@Pipe({ name: 'WithStatus', pure: true })
export class TaskStatusFilter implements PipeTransform{
transform(value: any, ...args: any[]): any {
console.log(value);// value is undefined
return value.filter(item => item.status == args[0]);
}
}
在 ajax 尚未完成的初始更改检测周期中,它会尝试评估 bindings
并将 tasks
中的值传递给 undefined
到 WithStatus
管道并抛出错误。对于这种情况,您只能在 Pipe 内处理它。
@Pipe({ name: 'WithStatus', pure: true })
export class TaskStatusFilter implements PipeTransform{
transform(value: any, ...args: any[]): any {
console.log(value);// value is undefined
return (value || []).filter(item => item.status == args[0]);
}
}
另一种方法是你应该在 DOM 树中注入 task-details
DOM 直到 ajax 使用 *ngIf
结构指令成功。
<template [ng-if]="tasks">
<task-details
*ngFor="let task of tasks | WithStatus: TaskStatus.New"
[task]="task">
</task-details>
</template>
你也可以使用 <ng-container>
而不是 <template>
,它允许使用与内联 *ngIf:
相同的语法
<ng-container *ngIf="tasks">
<task-details
*ngFor="let task of tasks | WithStatus: TaskStatus.New"
[task]="task">
</task-details>
</ng-container>
你可以试试*ngIf="task"。在数据到达之前,它不会初始化您的管道。
<div *ngIf="tasks" >
<task-details *ngFor="let task of tasks | WithStatus: TaskStatus.New"
[task]="task"></task-details>
</div>
我有一个调用 REST 端点的服务:
import { Task } from './task';
import { TaskStatus } from './task-status';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
@Injectable()
export class TaskService {
constructor(private http: Http){
}
getTasks() {
return this.http.get('http://localhost:8080/tasks').map(res => res.json()).map(rest => rest._embedded.tasks);
}
}
端点returns结果如下:
{
"_embedded": {
"tasks": [
{
"title": "zxc",
"description": "zxc",
"status": "New",
"_links": {
"self": {
"href": "http://localhost:8080/tasks/1"
},
"task": {
"href": "http://localhost:8080/tasks/1"
}
}
},
{
"title": "asd",
"description": "qweqwe",
"status": "New",
"_links": {
"self": {
"href": "http://localhost:8080/tasks/2"
},
"task": {
"href": "http://localhost:8080/tasks/2"
}
}
}
]
},
"_links": {
"self": {
"href": "http://localhost:8080/tasks"
},
"profile": {
"href": "http://localhost:8080/profile/tasks"
}
},
"page": {
"size": 20,
"totalElements": 3,
"totalPages": 1,
"number": 0
}
}
我在这个组件中使用服务:
@Component({
selector: 'app-mycomp',
templateUrl: './my.component.html',
styleUrls: ['./my.component.css']
})
export class MyComponent implements OnInit {
tasks: Array<Task>;
constructor(private taskService:TaskService) {
taskService.getTasks()
.subscribe(tasks => this.tasks = tasks,
err => console.error(err),
() => console.log('done'));
}
}
模板看起来像这样;
<task-details *ngFor="let task of tasks" [task]="task"></task-details>
这按预期工作,但是当我尝试在模板中使用管道时:
<task-details *ngFor="let task of tasks | WithStatus: TaskStatus.New" [task]="task"></task-details>
我收到错误 "Cannot read property 'filter' of undefined"。
管道实现如下:
import { Pipe, PipeTransform } from '@angular/core';
import { TaskStatus } from './task-status';
@Pipe({ name: 'WithStatus', pure: true })
export class TaskStatusFilter implements PipeTransform{
transform(value: any, ...args: any[]): any {
console.log(value);// value is undefined
return value.filter(item => item.status == args[0]);
}
}
在 ajax 尚未完成的初始更改检测周期中,它会尝试评估 bindings
并将 tasks
中的值传递给 undefined
到 WithStatus
管道并抛出错误。对于这种情况,您只能在 Pipe 内处理它。
@Pipe({ name: 'WithStatus', pure: true })
export class TaskStatusFilter implements PipeTransform{
transform(value: any, ...args: any[]): any {
console.log(value);// value is undefined
return (value || []).filter(item => item.status == args[0]);
}
}
另一种方法是你应该在 DOM 树中注入 task-details
DOM 直到 ajax 使用 *ngIf
结构指令成功。
<template [ng-if]="tasks">
<task-details
*ngFor="let task of tasks | WithStatus: TaskStatus.New"
[task]="task">
</task-details>
</template>
你也可以使用 <ng-container>
而不是 <template>
,它允许使用与内联 *ngIf:
<ng-container *ngIf="tasks">
<task-details
*ngFor="let task of tasks | WithStatus: TaskStatus.New"
[task]="task">
</task-details>
</ng-container>
你可以试试*ngIf="task"。在数据到达之前,它不会初始化您的管道。
<div *ngIf="tasks" >
<task-details *ngFor="let task of tasks | WithStatus: TaskStatus.New"
[task]="task"></task-details>
</div>