Angular 8 сделать элемент квадратным броском Ошибка: ExpressionChangedAfterItHasBeenCheckedError - PullRequest
1 голос
/ 07 марта 2020

Я пытаюсь динамически создать квадрат. Я нашел решение здесь .

<div #div (window:resize)="0" [ngStyle]="{'height.px': div?.offsetWidth || 1 }">

Однако выдает ошибку;

SiparisGirComponent.html:98 ERROR Error: ExpressionChangedAfterItHasBeenCheckedError: 
Expression has changed after it was checked. Previous value: 'height.px: 1'. Current value: 
'height.px: 135'.

Работает, но ошибка меня беспокоит. Может кто-нибудь помочь мне избавиться от этой ошибки.

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

Ответы [ 3 ]

0 голосов
/ 16 марта 2020

Это потому, что в режиме разработки angular проверяет, что значения не изменились после обновления привязок. Изменение значений между ними может вызвать побочный эффект, например, неправильное отображение значения (см. Хорошее объяснение здесь )

В вашем примере:

  • обнаружение изменений выполняется
  • div еще не создан
  • angular присваивает значение 1 свойству div style.height
  • браузер dr aws div
  • angular снова запускает обнаружение изменений (только в режиме разработки)
  • div существует, поэтому значение style.height больше не будет равно 1. Angular затем выдает ExpressionChangedAfterItHasBeenCheckedError ошибку

Вам необходимо уведомить angular об изменении, используя ChangeDectorRef.detectChanges(). Для этого вы можете вызвать метод компонента, поскольку вы не можете вызвать его напрямую из шаблона.

component.ts

  lastWidth = 1;
  @ViewChild('div', {static: true}) div: ElementRef;
  constructor(private cdr:ChangeDetectorRef)
  {

  }

  getWidth()
  {
    if(this.div)//Wzit until element is created
    {
       //Only call detectChanges if the previous value has changed
      if(this.div.nativeElement.offsetWidth  != this.lastWidth)
      {
        this.lastWidth = this.div.nativeElement.offsetWidth ;
        this.cdr.detectChanges();
      }
    }
    return this.lastWidth;

  }

компонента. html

<div #div  (window:resize)="0" [ngStyle]="{'height.px': getHeight() }">

Я создал демонстрацию стекаблика Демонстрация стекаблика , где вы можете динамически изменять размер div.

Примечание: вы также можете перенести изменение в setTimeout вызов, который также решит проблему. Однако это снова запустит обнаружение изменений для всего приложения, а не только для интересующего вас компонента.

0 голосов
/ 17 марта 2020

Эта проблема возникает только в режиме разработки. Он введен в Angular, чтобы избежать проблемы цикла в цикле дайджеста (проблема в AngularJS).

После успешного выполнения цикла обнаружения изменений для привязок, Angular снова проверяет привязки, изменились они или нет еще раз, запустив обнаружение изменений. И если любое из значений изменяется, Angular выдает эту ошибку в консоли.

Пожалуйста, go через этот интересный блог, чтобы понять Обнаружение изменений в Angular и значение этой ошибки

Как уже говорилось, это потому, что Angular запускает другой цикл, чтобы проверить, изменилось ли значение какой-либо привязки или нет. Таким образом, вы можете легко пропустить последовательное изменение, запустив асинхронно с помощью setTimeout.

setTimeout(() => {
  this.lastWidth = this.div.nativeElement.offsetWidth;
});

Вы также можете использовать обнаружение изменений вручную, как указано выше.

Пожалуйста, посмотрите этот рабочий стекблиц: https://stackblitz.com/edit/angular-nvwium

0 голосов
/ 16 марта 2020

Он работает в режиме разработки, но, вероятно, не будет работать правильно в производственной сборке. Попробуйте взглянуть на эту статью , чтобы понять, что означает эта ошибка.

Чтобы избавиться от этой ошибки, вы можете вручную принудительно запустить Change Detection для повторного запуска после Вы устанавливаете высоту.

Я создал простое Демонстрация StackBlitz

HTML:

<div #div (window:resize)="0" [ngStyle]="{'height.px': dynamicDivHeight }"></div>

TS:

...
export class Component implements AfterViewInit  {

    @ViewChild('div', { static: false } ) div: ElementRef<HTMLDivElement>; // element reference

    dynamicDivHeight: number = 1;

    constructor(private changeDetectorRef: ChangeDetectorRef) {
    }


    ngAfterViewInit() {    // if you are working with native html elements, you should be doing it in AfterViewInit hook
        this.dynamicDivHeight = this.div.nativeElement.offsetWidth;     // set the dynamic height
        this.changeDetectorRef.detectChanges();     // manually force change detection
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...