2

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);
    }
}

エンドポイントは次のような結果を返します。

{
  "_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>

「未定義のプロパティ 'filter' を読み取れません」というエラーが表示されました。

パイプの実装は次のとおりです。

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]);
    }
}
4

2 に答える 2

3

最初の変更検出サイクルで、その時点で ajax が完了していないときに、値を評価してパイプにbindings渡そうとすると、エラーがスローされます。そのような場合は、パイプ内でのみ処理する必要があります。tasksundefinedWithStatus

@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]);
    }
}

もう 1 つの方法は、構造ディレクティブtask-detailsを使用して ajax が成功するまで、DOM ツリー内に DOMを挿入することです。*ngIf

<template [ng-if]="tasks">
  <task-details 
    *ngFor="let task of tasks | WithStatus: TaskStatus.New" 
    [task]="task">
  </task-details>
</template>

代わりに、インライン *ngIf と同じ構文を使用できるようにする<template>こともできます。<ng-container>

<ng-container *ngIf="tasks">
  <task-details 
    *ngFor="let task of tasks | WithStatus: TaskStatus.New" 
    [task]="task">
  </task-details>
</ng-container>
于 2016-09-24T15:47:00.810 に答える
1

*ngIf="task"を試すことができます。データが到着するまで、パイプは初期化されません。

<div *ngIf="tasks" >
<task-details *ngFor="let task of tasks | WithStatus: TaskStatus.New" 
              [task]="task"></task-details>
</div>
于 2016-09-24T15:48:31.090 に答える