ExpressionChangedAfterItHasBeenCheckedError: путем итерации карты - PullRequest
1 голос
/ 20 октября 2019

У меня есть простой Angular-компонент, который при рендеринге выдает следующую ошибку:

MyComponent.html:10 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked.
Previous value: 'ngForOf: [object Map Iterator]'. 
Current value: 'ngForOf: [object Map Iterator]'.

Ошибка выдается дважды, даже когда перемещается в минимальный Angular-проект без другого кода (простоAppComponent, обертывающий этот компонент).

Я свернул код до минимальной формы, которая все еще воспроизводит проблему. Я заменил службу данных на жестко запрограммированную наблюдаемую.

Компонент

@Component({
  selector: 'my-component',
  templateUrl: './my.component.html',
  styleUrls: ['./my.component.scss'],
})
export class MyComponent implements OnInit, OnDestroy {

  private cobs: Map<number, string>;
  private cobSub: Subscription;

  constructor() {}

  ngOnInit() {
    // originally data comes from a service...
    this.cobSub = of(new Map<number, string>([[1, 'a'], [2, 'b']]))
      .subscribe({
        next: cobs => { this.cobs = cobs; },
      });
  }

  ngOnDestroy(): void {
    this.cobSub.unsubscribe();
  }

}

Обратите внимание, что asyncPipe более распространено для использования в сценарии такого рода, но я не могу его использовать.

Шаблон

<div>
  <table *ngIf="cobs">
    <tr>
      <th>Id</th>
      <th>Class of Business</th>
    </tr>
    <tr *ngFor="let key of cobs.keys()">
      <td>{{key}}</td>
      <td>{{cobs.get(key)}}</td>
    </tr>
  </table>
</div>

Почему возникает проблема?

Как ее можно исправить?

1 Ответ

3 голосов
/ 20 октября 2019

Это проблема с тем, как вы выполняете итерации на карте, вы можете попробовать:

export class AppComponent implements OnInit {
  private cobs = new Map<number, string>();
  private cobSub: Subscription;

  constructor() {}

  ngOnInit() {
    this.cobSub = of(new Map<number, string>([[1, 'a'], [2, 'b']]))
      .subscribe( cobs => {
        this.cobs = cobs;
      });
  }

  getKeys(map){
    return Array.from(map.keys()); // add it
  }
  ngOnDestroy(): void {
    this.cobSub.unsubscribe();
  }
}

в html:

<div>
  <table *ngIf="cobs">
    <tr>
      <th>Id</th>
      <th>Class of Business</th>
    </tr>
    <tr *ngFor="let key of getKeys(cobs)">
      <td>{{key}}</td>
      <td>{{cobs.get(key)}}</td>
    </tr>
  </table>
</div>

demo

и если вы используете Angular 6.1+, вы можете использовать трубу по умолчанию keyvalue :

<tr *ngFor="let key of cobs | keyvalue">
          <td>{{key.key}}</td>
          <td>{{key.value}}</td>
        </tr>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...