* ngДля отображения данных, но выдает ошибку «undefined» - PullRequest
0 голосов
/ 04 декабря 2018

У меня есть директива * ngFor, которая работает и отображает данные в моем браузере, как и ожидалось.Хотя моя консоль в Chrome показывает «неопределенные» ошибки.

http.service.ts:

getExerciseProgress(exId: number): Observable<Exercise> {
    return this.http.get<Exercise>(this.baseURL + 'exercises/GetProgressionByExerciseId/' + exId)
  }

view-exerc.component.ts:

 exercise: Exercise;

  constructor(private http: HttpService) { }


  ngOnInit() {
    this.http.getExerciseProgress(7).subscribe(ex =>{
      this.exercise = ex;
      console.log(this.exercise);
    });
  }

7, переданный как параметр, предназначен для тестирования и когдаЯ регистрирую результат, объект, кажется, то, что я ищу.Объект Exercise с вложенным массивом Progress.

view-exerc.component.html:

<p *ngFor="let p of exercise.progress">{{ p.bpm }}</p>

Эта строка выше выдает следующее сообщение в моем окне консоли Chrome.Msgstr "ОШИБКА TypeError: Невозможно прочитать свойство 'progress' из неопределенного".Несмотря на это, мой браузер отображает правильную информацию.

Модели на стороне клиента (на всякий случай, если это уместно):

export class Exercise {

id: number;
description: string;
progress: Progress[];

constructor(id: number, description: string, progress: Progress[]){
    this.id = id;
    this.description = description;
    this.progress = progress;
}

export class Progress {

id: number;
dateAttempted: Date;
bpm: number;

constructor(id: number, dateAttempted: Date, bpm: number){
    this.id = id;
    this.dateAttempted = dateAttempted;
    this.bpm = bpm;
}

}

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 04 декабря 2018

Это состояние гонки: при первой загрузке шаблона this.exercise по-прежнему undefined.Затем, когда наблюдаемое разрешается и присваивается значение, запускается цикл обнаружения изменений , запускается *ngFor, и вы видите значения.

Существует два типичных шаблона, которые необходимо исправить.this:

Используйте оператор elvis (вероятно, лучше всего в вашем случае, потому что у вас есть только один метод доступа):

<p *ngFor="let p of exercise?.progress">{{ p.bpm }}</p>

?. означает «получить доступ к свойствусправа от этого оператора, если операнд слева определен ".Если написать это так, очевидно, что они могут быть связаны: exercise?.progress?.timer?.started

Или использовать защитный элемент для элемента контейнера, что лучше, когда у вас много средств доступа и вы не хотите повторять ?. везде:

<ng-container *ngIf="exercise">
  <p *ngFor="let p of exercise.progress">{{ p.bpm }}</p>
<ng-container>

В приведенном выше примере я использовал <ng-container />, потому что он не отображается в DOM, но вы можете также легко использовать его на реальном элементе, таком как <div />.Это обычно используется в шаблоне *ngIf="exercise; else no-data", где #no-data - это другой ng-шаблон, который заменяет div при загрузке ваших данных.


Примечание к сведению, поскольку Angular использует полифилы,вы можете безопасно использовать шаблонные строки в вашем TypeScript.Это означает, что вы можете написать

this.baseURL + 'exercises/GetProgressionByExerciseId/' + exId

как

`${this.baseURL}/exercises/GetProgressionByExerciseId/${exId}`

, что некоторым людям легче читать.

0 голосов
/ 04 декабря 2018

Ваш DOM, похоже, ищет объект прогресса внутри упражнения до того, как сервисный вызов завершен, и у вас есть доступные данные.

Вы должны перебрать его, когда он будет доступен, это означает, что вызов API завершен иу вас есть данные:

<p *ngFor="let p of exercise?.progress">{{ p.bpm }}</p>

Или используйте *ngIf для достижения этого.

0 голосов
/ 04 декабря 2018

Можете ли вы попробовать это: <p *ngFor="let p of exercise?.progress">{{ p.bpm }}</p>

Я предполагаю, что угловая попытка сначала отобразить что-то, даже если ваши данные не являются init.

...