ngx datatable Ошибка: ExpressionChangedAfterItHasBeenCheckedError: выражение изменилось после его проверки [duplicate]

Sine Python 3.5 вы можете использовать функцию math.isclose(), если условия

import math

if math.isclose(0.1 + 0.2, 0.3, abs_tol=0.01):
    pass
153
задан SnareChops 7 February 2016 в 22:38
поделиться

13 ответов

Во-первых, обратите внимание, что это исключение будет генерироваться только при запуске вашего приложения в режиме dev (что по умолчанию имеет значение по умолчанию в бета-0): Если вы вызываете enableProdMode() при загрузке приложения он не будет сброшен ( см. обновленный plunk ).

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

В вашем плунге привязка {{message}} изменяется вашим вызовом на setMessage(), что происходит в крюк ngAfterViewInit, который происходит как часть начального поворота обнаружения изменений. Это само по себе не является проблематичным - проблема в том, что setMessage() изменяет привязку, но не вызывает новый раунд обнаружения изменений, а это означает, что это изменение не будет обнаружено до тех пор, пока какой-либо другой раунд обнаружения изменений не будет запущен где-то в другом месте ,

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

Обновление в ответ на все запросы для примера того, как это сделать: @ Решение Tycho работает, как и три метода из , на которые указывает ответ @MarkRajcok. Но, честно говоря, все они кажутся уродливыми и неправильными для меня, такими, как хаки, которые мы привыкли опираться на ng1.

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

ИМХО, более идиоматический подход «Угловой 2» приближается к этому, это что-то вроде: ( plunk )

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message | async}} </div>`
})
export class App {
  message:Subject<string> = new BehaviorSubject('loading :(');

  ngAfterViewInit() {
    this.message.next('all done loading :)')
  }
}
110
ответ дан Community 31 August 2018 в 20:57
поделиться

В статье Все, что вам нужно знать о ошибке ExpressionChangedAfterItHasBeenCheckedError , объясняет поведение в деталях.

Проблема с настройкой заключается в том, что ngAfterViewInit выполненные после изменения обнаружения обработанных обновлений DOM. И вы эффективно меняете свойство, которое используется в шаблоне в этом хук, что означает, что DOM необходимо повторно отобразить:

  ngAfterViewInit() {
    this.message = 'all done loading :)'; // needs to be rendered the DOM
  }

, и для этого потребуется другой цикл обнаружения изменений и угловой по дизайну (g6)

      обновляет свойство асинхронно либо с помощью setTimeout, Promise.then, либо с асинхронными наблюдаемыми ссылками в шаблоне
    • выполнить обновление свойства в hook перед обновлением DOM - ngOnInit, ngDoCheck, ngAfterContentInit, ngAfterContentChecked.
16
ответ дан AngularInDepth.com 31 August 2018 в 20:57
поделиться

ngAfterViewChecked () работал для меня:

import { Component, ChangeDetectorRef } from '@angular/core'; //import ChangeDetectorRef

constructor(private cdr: ChangeDetectorRef) { }
ngAfterViewChecked(){
   //your code to update the model
   this.cdr.detectChanges();
}
14
ответ дан Azam Alvi 31 August 2018 в 20:57
поделиться

Я исправил это, добавив ChangeDetectionStrategy из углового ядра.

import {  Component, ChangeDetectionStrategy } from '@angular/core';
@Component({
  changeDetection: ChangeDetectionStrategy.OnPush,
  selector: 'page1',
  templateUrl: 'page1.html',
})
27
ответ дан Biranchi 31 August 2018 в 20:57
поделиться

Не можете ли вы использовать ngOnInit, потому что вы просто изменяете переменную-член message?

Если вы хотите получить ссылку на дочерний компонент @ViewChild(ChildComponent), вам действительно нужно подождать это с ngAfterViewInit.

Грязное исправление - вызвать updateMessage() в следующем цикле событий, например, setTimeout.

ngAfterViewInit() {
  setTimeout(() => {
    this.updateMessage();
  }, 1);
}
23
ответ дан Jo VdB 31 August 2018 в 20:57
поделиться

Для этого я попытался ответить выше, многие из них не работают в последней версии Angular (6 или новее)

Я использую элемент управления Material, который требует изменений после первого связывания.

    export class AbcClass implements OnInit, AfterContentChecked{
        constructor(private ref: ChangeDetectorRef) {}
        ngOnInit(){
            // your tasks
        }
        ngAfterViewInit() {
            this.ref.detectChanges();
        }
    }

Добавление моего ответа так, это помогает решить определенную проблему.

0
ответ дан MarmiK 31 August 2018 в 20:57
поделиться

Вы также можете создать таймер с помощью rxjs Observable.timer, а затем обновить сообщение в своей подписке =>

Observable.timer (1) .subscribe (() => this.updateMessage ()) ;

0
ответ дан rabinneslo 31 August 2018 в 20:57
поделиться

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

см .: https://angular.io/docs/ts/latest/guide/lifecycle-hooks.html#!#afterview

, поэтому код будет просто:

import { Component } from 'angular2/core'

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message}} </div>`,
})
export class App {
  message: string = 'loading :(';

  ngAfterContentChecked() {
     this.message = 'all done loading :)'
  }      
}

см. рабочую демонстрацию на Plunker.

6
ответ дан RedPelle 31 August 2018 в 20:57
поделиться

Он выдает ошибку, потому что ваш код обновляется при вызове ngAfterViewInit (). Значение вашего начального значения изменилось, когда ngAfterViewInit имеет место. Если вы вызываете это в ngAfterContentInit (), то он не будет вызывать ошибку.

ngAfterContentInit() {
    this.updateMessage();
}
1
ответ дан Sandip Patel 31 August 2018 в 20:57
поделиться

Я уже пробовал это решение: (Это сработало!) [/ ​​g1]

    export class BComponent {
    name = 'I am B component';
    @Input() text;

    constructor(private parent: AppComponent) {}

    ngOnInit() {
        setTimeout(() => {
            this.parent.text = 'updated text';
        });
    }

    ngAfterViewInit() {
        setTimeout(() => {
            this.parent.name = 'updated name';
        });
    }
}

Вы можете прочитать более подробно здесь: https://blog.angularindepth.com/everything-you-need -в-ноу-о-The-expressionchangedafterithasbeencheckederror-ошибок e3fd9ce7dbb4

0
ответ дан Tang Thanh Tam 31 August 2018 в 20:57
поделиться

Я не могу прокомментировать сообщение @Biranchi, так как у меня нет достаточной репутации, но она исправила проблему для меня.

Одно замечание! Если добавить changeDetection: ChangeDetectionStrategy.OnPush на компонент не работает, а его дочерний компонент (немой компонент) попробуйте добавить его к родительскому объекту.

Это исправило ошибку, но мне интересно, каковы побочные эффекты этого.

0
ответ дан TKDev 31 August 2018 в 20:57
поделиться

Вы также можете поместить свой вызов updateMessage () в ngOnInt () - Method, по крайней мере, он работает для меня

ngOnInit() {
    this.updateMessage();
}

. В RC1 это не вызывает исключение

4
ответ дан Tobias Gassmann 31 August 2018 в 20:57
поделиться

Как указано в drewmoore, правильным решением в этом случае является ручное инициирование обнаружения изменений для текущего компонента. Это делается с использованием метода detectChanges() объекта ChangeDetectorRef (импортированного из angular2/core) или его метода markForCheck(), который также обновляет любые родительские компоненты. Соответствующий пример :

import { Component, ChangeDetectorRef } from 'angular2/core'

@Component({
  selector: 'my-app',
  template: `<div>I'm {{message}} </div>`,
})
export class App {
  message: string = 'loading :(';

  constructor(private cdr: ChangeDetectorRef) {}

  ngAfterViewInit() {
    this.message = 'all done loading :)'
    this.cdr.detectChanges();
  }

}

Здесь также Plunkers демонстрируют ngOnInit , setTimeout и enableProdMode на всякий случай.

158
ответ дан Tycho 31 August 2018 в 20:57
поделиться
Другие вопросы по тегам:

Похожие вопросы: