Angular: ИСКЛЮЧЕНИЕ: выражение было изменено после проверки.

Созданный на 18 дек. 2015  ·  147Комментарии  ·  Источник: angular/angular

Самый полезный комментарий

Это не ошибка, это функция режима разработки, работающая должным образом. Вызов enableProdMode( ) - просмотр обновленного блока при загрузке приложения предотвращает создание исключения.

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

В вашем plunk у вас есть привязка [attr.spinner]=isLoading , и isLoading изменяется в результате вашего вызова this.load() , который происходит, когда запускается ngAfterViewInit , что происходит как часть первого хода обнаружения изменений. Само по себе это не проблема - проблема в том, что this.load() изменяет привязку, но не запускает новый раунд обнаружения изменений, что означает, что эта привязка не будет обновлена ​​до следующего раунда обнаружения изменений.

Все 147 Комментарий

Я столкнулся с аналогичной проблемой, и, похоже, это связано с тем, как инициализируется дочерний элемент и как родитель может обновлять дочерний элемент в рамках процесса инициализации. У меня есть аналогичный образец с уродливым обходным путем с использованием зоны: http://plnkr.co/edit/GI45u805pnFUtFeORnxn?p=preview , причем обходной путь выглядит следующим образом:

конструктор (частный _zone: NgZone) {}

ngAfterViewInit (): void {
this._zone.overrideOnTurnDone (() => {
this.child.title = 'заголовок от родителя';
});
}

Это не ошибка, это функция режима разработки, работающая должным образом. Вызов enableProdMode( ) - просмотр обновленного блока при загрузке приложения предотвращает создание исключения.

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

В вашем plunk у вас есть привязка [attr.spinner]=isLoading , и isLoading изменяется в результате вашего вызова this.load() , который происходит, когда запускается ngAfterViewInit , что происходит как часть первого хода обнаружения изменений. Само по себе это не проблема - проблема в том, что this.load() изменяет привязку, но не запускает новый раунд обнаружения изменений, что означает, что эта привязка не будет обновлена ​​до следующего раунда обнаружения изменений.

Мне нужно настроить свой компонент в afterViewInit потому что здесь инициализирован ChildView . Как правильно внести это изменение в isLoading ? Обернуть вызов this.load на setTimeout ?

Вам просто нужно сделать что-нибудь, что угодно, что вызовет еще один раунд обнаружения изменений во время этого метода - испустить событие, что угодно. Обернуть его в тайм-аут (возврат в очередь на ng1 :-P) - это один из способов, который сработает, но мне кажется, что в ng2 очень беспорядочно.

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

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

@ AerisG222 то же

@robwormald Да, в этом случае я мог бы выполнить привязку свойств. Реальный случай, который у меня есть, также включает в себя другое свойство, которое немного сложнее - массив настраиваемых объектов, но это тоже, безусловно, может быть установлено через привязку свойства.

Я полагаю, что если бы не было такой вещи, как @ViewChild , меня бы не волновало это слишком много, так как это был бы единственный разумный способ передать информацию вниз. Тем не менее, я был очень взволнован, увидев @ViewChild так что я мог работать над ссылками на компоненты в коде. Это упрощает разметку и обеспечивает больший контроль с помощью кода, что дополнительно ценно для машинописного текста, поскольку есть больше поддержки инструментов (например, intellisense и проверка времени компиляции). Это также упрощает компонент контейнера, поскольку ему не нужно отслеживать переменные-члены, которые предназначены только для использования в качестве состояния для дочернего элемента.

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

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

inflate.ts

import {Component, Input, Renderer, ElementRef, AfterViewInit, ViewChild} from 'angular2/core';

@Component({
  selector: '[inflate]',
  templateUrl: './inflate.html',
  styleUrls: ['./inflate.css']
})
export class Inflate implements AfterViewInit {
  @Input('inflate') url: string;
  @ViewChild('holder') holder: ElementRef;
  isLoaded = false;
  isLoading = false;

  constructor(private renderer: Renderer) {}

  ngAfterViewInit() {
    setTimeout(_=> this.inflate()); // BUGFIX: https://github.com/angular/angular/issues/6005#issuecomment-165911194
  }

  inflate() {
    let bounds = <ClientRect>this.holder.nativeElement.getBoundingClientRect();
    if(bounds.bottom > 0 && bounds.top < window.innerHeight) {
      this.isLoading = true;
      let img = new Image();
      img.src = this.url;
      img.onload = _=> {
        this.isLoaded = true;
        this.isLoading = false;
        this.renderer.setElementStyle(this.holder,
          'background-image', 'url("' + this.url + '")');
      };
    }
  }
}

inflate.html

<image-holder #holder></image-holder>
<spinner *ngIf="isLoading"></spinner>

Мне нужно сохранить изображение не на хосте, потому что, хотя оно исчезает с анимацией по завершении загрузки, это не должно влиять на непрозрачность фона хоста.

У меня потенциально связанная проблема с вложенной директивой.
http://plnkr.co/edit/myX2Alx9jie2q0FDIME7?p=preview
Здесь я привязываюсь к ngStyle в progressBar.ts.
Я регистрирую объект стилей перед тем, как вернуться, чтобы доказать, что они равны.
Я также получаю ExpressionChangedAfterItHasBeenCheckedException.

@ svi3c вы фактически возвращаете _ другой_ объект. Каждый вызов функции возвращает новый экземпляр объекта, который «равен» предыдущему с точки зрения ключей / значений, но не с точки зрения экземпляров / ссылок.

Есть несколько способов справиться с этой ситуацией:

  • обновлять значения в одном экземпляре объекта вместо возврата новой копии
  • с использованием стратегии ChangeDetectionStrategy.OnPush , поэтому ваша функция вызывается только при изменении одного из входных данных, например: http://plnkr.co/edit/NWyVoTtkiAzqWJphLMbi?p=preview

Возможно, вы захотите проверить https://github.com/ng-bootstrap/core/blob/master/src/progressbar/progressbar.ts в качестве еще одного примера директивы индикатора выполнения для ng2 (с использованием загрузочного HTML / CSS)

@ pkozlowski-opensource Большое спасибо!
Я читаю только https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngstyle и еще не наткнулся на стратегии обнаружения изменений. Замечательно! :)

@ Дрю-Мур:

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

Можете ли вы посоветовать, какой _правильный_ и _ простой_ способ повторно запустить обнаружение изменений в ngAfterViewInit - предполагая, что все, что нужно, - это свойство, которое нужно обновить. ApplicationRef.tick() здесь не работает, так как это вызывает исключение «ApplicationRef.tick вызывается рекурсивно»; генерировать событие только для того, чтобы вызвать обнаружение изменений, кажется неправильным (и не сработало для меня), как и setTimeout .

На основании приведенных здесь комментариев кажется довольно распространенным требованием обновить связанное свойство в ngAfterViewInit (из-за зависимости от дочернего компонента), поэтому в Angular 2, похоже, отсутствует простой способ сделать это.

Если обновление связанного свойства в ngAfterViewInit - это _неправильный_ поступок, какова альтернатива?

Вот быстрый:

Вызов:
Установите высоту элемента dom (с помощью определенной формулы) на основе его ширины отрисовки.

Ожидание:
Когда элемент будет отрисован, получите ширину и на ее основе вычислите высоту.

Реальность:
setTimeout ?!

  ngAfterViewInit() {
    window.setTimeout(() =>
      this.elementHeight = (this.nativeElement.offsetWidth * this.randomImage.dim.h) / this.randomImage.dim.w
    )
  }

@Birowsky Plunker?

@zoechi Вот пример: http://plnkr.co/edit/MML5uHEFQdL0k0TA5HtY

Вы можете переключить setTimeout в app/app.component.ts#21 в ловушке жизненного цикла ngAfterViewInit .

Я также столкнулся с чем-то похожим при попытке реализовать метод writeValue( newValue ) пользовательского ngModel valueAccessor . Когда я пытаюсь применить newValue к компоненту, он сообщает мне, что значение изменилось (в плохом смысле). Как вы все заметили, упаковка его в setTimeout () «исправляет» это; но не в хорошем смысле.

У меня есть еще один пример . Это немного проще в том, что @HostBinding() устанавливается и информируется QueryList .

То же, что и мой номер 5950.

Вот несколько рекомендаций, как это сделать чисто.
http://stackoverflow.com/questions/34827334/triggering-angular2-change-detection-manually

Однако я все еще использую setTimeout потому что я не мог заставить их делать то, что мне нужно. Похоже, я мог бы ChangeDetectorRef.detectChanges() в конце обратного вызова и запустить CD .... Я что-то упускаю? Может быть, это поможет кому-нибудь из вас, ребята.

Я использую расширения источника мультимедиа HTML5 для создания аудиоконтекста на основе элемента видео, поэтому требуется использование @ViewChild . Основываясь на звуковом контексте, я пытаюсь отобразить некоторую информацию, например количество каналов. Однако я тоже столкнулся с этой проблемой. Как правильно это обойти?

@ElsewhereGames Трудно сказать, не увидев реального кода. Можете ли вы создать Plunker

@zoechi У меня нет фактической ошибки, о которой я @robwormald ). Фактический API см. В документации по createMediaElementSource .

Я отправил еще в январе с проблемой _ngModel_. Теперь я снова вернулся с проблемой _ViewChildren_. Однако, в отличие от некоторых других примеров, я на самом деле ничего не пытаюсь сделать в своей демонстрации. То есть мои контроллеры имеют нулевую логику - это все метаданные и привязки представлений. Таким образом, я не уверен, где у меня даже есть место для маневра, чтобы _ мешать вещи_:

http://www.bennadel.com/blog/3040-i-have-a-fundamental-misunderstanding-of-change-detection-in-angular-2-beta-8.htm

Возникла аналогичная проблема, но можно было переписать код, чтобы обойти ее. Я хорошо посмеялся над сообщением

https://github.com/angular/angular/issues/6618

До сих пор всегда был способ обойти это, но я предлагаю его здесь снова, по крайней мере, механизм обнаружения изменений мог бы использовать дополнительную документацию. @bennadel Ваша проблема напоминает мне другую проблему,

https://github.com/angular/angular/issues/5177

где для решения этой проблемы было предложено добавить дополнительный перехватчик жизненного цикла OnBeforeBinding / OnBeforeRendering. Похоже, это решение также решит вашу проблему.

@tandu просто замените ngAfterViewInit на ngOnInit

@tandu на самом деле не имеет значения, когда запустится ваш счетчик (загрузка дочернего элементе - для пользователя все это загружается), имеет значение только тогда, когда вам нужно его выключить. Вы можете отключить его в "ngAfterViewInit", используя setTimeout (я согласен, что это некрасиво), но это будет неправильно - дочерний компонент должен запускать событие, когда загрузка изображения завершена, для родительского компонента. Загрузка дочернего компонента и загрузка изображения - это два разных события.

@ e-oz https://github.com/angular/angular/issues/6005#issuecomment -165951692 Я обращаюсь к дочерним границам, чтобы определить, следует ли начинать загрузку изображения.

@tandu, и вы можете переместить всю эту проверку в код дочернего компонента (это будет законно в ngAfterViewInit дочернего компонента) и отправить событие родительскому, когда нужно изменить isLoading.

@ e-oz Я определяю компонент как #holder в html: <image-holder #holder></image-holder> . Так что для него нет js файла.

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

В вс, 13 марта 2016 в 15:18 tandu [email protected] написал:

@ e-oz https://github.com/e-oz Я определяю компонент как #holder в html:

держатель>

. Так что для него нет js файла.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/angular/angular/issues/6005#issuecomment -195963389.

Я также могу использовать element.getElementsByTagsName или аналогичные методы и не использовать ChildComponent. Определенно существуют обходные пути. Я в порядке с setTimeout fix. Проблема в том, что имя метода предполагает, что его можно использовать для определения некоторой логики, которая хочет, чтобы дочерние компоненты были инициализированы и привязаны к компоненту, но метод не сообщает, что он запускается в середине цикла обнаружения изменений, и поэтому у нас есть длинный ветка жалоб от разных людей.

@tandu Абсолютно согласен с вами в этом, очень досадное ограничение.

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

    constructor(private _changeDetectionRef : ChangeDetectorRef) { }

    ngAfterViewInit() : void {
        // your code

        this._changeDetectionRef.detectChanges();
    }

Я получаю такое же исключение при использовании проверки формы (требуется ввод). Связано с этой проблемой?

Plunker: http://plnkr.co/edit/Fp6XT5mC6ZCB14Z1gvTi?p=preview

@eivindr быстро просмотрел, и я раньше не видел ngFormControl на вводе, не могу понять, почему и что это будет значить, поскольку он должен идти в элементе формы, чтобы привязать его к группе управления, и отдельный ввод будет иметь соответствующий ngControl. В любом случае в вашем плунжере удалите

 [ngFormControl]="formModel.find('title')" 

и это исправляет вашу ошибку.

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

http://www.bennadel.com/blog/3056-host-bindings-are-breaking-the-ngmodel-bridge-in-angular-2-beta-11.htm

Я должен полагать, что на данный момент это ошибка, потому что у компонента есть две вещи, которые зависят от ввода - шаблон представления и привязки хоста - и _ только одна из них_ вызывает исключение изменения. Если бы они оба вызвали проблему, я бы подумал о другом; но, поскольку только один из них вызывает проблему, это, должно быть, ошибка, верно?

@eivindr У меня такая же проблема, когда я начинаю с пустой формы, а затем программно устанавливает значение элементов управления формы. Вы нашли обходной путь?

@MarkPerryBV Нет, я все еще получаю сообщение "изменилось после проверки" при использовании обязательно. То же самое при использовании валидатора шаблонов. Но minLength и т. Д. Работает.

@ user414 Если я удалю [ngFormControl] ... на вводе не будет "обязательной" проверки.

@MarkPerryBV Я нашел обходной путь, который у меня работает (пока). Пришлось включитьProdMode (). Я использую ngIf для входов, поэтому мне также пришлось выполнить ChangeDetectorRef.detectChanges () после того, как вход был отрендерен (в противном случае вход был недействительным, несмотря на наличие содержимого).

Использование enableProdMode() самом деле ничего не исправляет - оно просто маскирует симптом, останавливая повторную проверку и сообщая вам, что что-то, вероятно, не так.

Исправление AerisG222 кажется лучше, чем использование setTimeout . Действительно ли предполагаемое поведение состоит в том, чтобы вручную запускать обнаружение изменений после вызова addControl() с помощью валидатора?

Та же проблема здесь после вызова addControl (). Я думаю, что addControl () должен вызывать ChangeDetectionRef.detectChanges ().

@CaptainCodeman Я знаю - это временное решение.

Это больше не будет работать в режиме разработки, когда я использую ng2 @ beta17 , [email protected] , zone. [email protected]. Мне все еще нужно вызвать ChangeDetectionRef.detectChanges ()

@eivindr вы можете обновить свой plnkr до исправления beta17?
Я схожу с ума по этому поводу, я отказываюсь подчиняться enableProdMode() .

@ AerisG222 Ваш подход у меня работает!

Использует ли подход, который опубликовал @ AerisG222, хороший подход? Да, это работает, но есть ли у кого совесть вручную запускать changeDetectionRef.detectChanges() ?

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

Действия по воспроизведению. Отправить форму с проверкой сотрудника. После обновления формы снова проверьте Is Employee.

Я использую changeDetectionRef.detectChanges () в функции отправки.

спасибо за это @ AerisG222 :)

Мне не нравится все это обходное решение setTimeout. Предлагаю следующее:

http://plnkr.co/edit/9umnTGsdFWhbaOBeftuZ?p=preview

Использование ChangeDetectorRef.detectChanges не всегда является хорошим подходом. Пример почему:

Родительский компонент вызывает общедоступный API дочерних компонентов во время его ngAfterViewInit . Этот вызов изменяет привязку ребенка. Вызов detectChanges от родителя тоже решит проблему, но это означает, что родитель должен знать, когда вызывать detectChanges после которого вызывается дочерний API. Вы заметите, что вызов detectChanges в дочернем методе, который изменяет привязку в этом случае, не работает, если вы хотите использовать ChangeDetectionStrategy.OnPush .

Я столкнулся с этой ошибкой при динамическом добавлении детей через ViewContainerRef.createComponent() и последующем обновлении дочернего экземпляра. Я использую RC2 (и стараюсь не использовать устаревшие вещи).

Сначала все работало нормально (сначала рендеринг), но потом я добавил компонент, который будет выдавать новые данные. Это событие было прослушано родительским компонентом, который обновил свой массив данных, запустив обнаружение изменений и заполнение новых динамических дочерних компонентов. Событие было инициировано отправкой формы. Если я нажал кнопку отправки, все было в порядке. Если я нажму Enter, чтобы сгенерировать отправку, это приведет к ошибке.

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

@ aerisg222 Нужно ли мне вызывать this._changeDetectionRef.detectChanges () после каждого изменения свойства дочернего элемента от родительского?

Я только что столкнулся с этой проблемой. У меня есть два родственных компонента, использующих один и тот же объект данных. Предполагается, что оба объекта могут обновлять источник данных. Другой источник действительно видит изменение в объекте, но запускает, что выражение изменилось после того, как оно было проверено. Предыдущее значение: «истина». Текущее значение: false

Это случилось со мной после обновления с RC1 до RC4

То же самое. Снова начал получать это после обновления с RC1 до RC4.

Может быть, об изменении, вызвавшем это, следовало сообщить как о критическом изменении в журнале изменений ... kuz, мои данные сейчас не работают.

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

То же самое. Динамическая загрузка компонентов через ViewComponentRef, похоже, ведет себя по-разному в RC2 и RC4, как и в RC1.

Вот мои рабочие зависимости:
"dependencies": {
"@ angular / common": "2.0.0-rc.1",
"@ angular / compiler": "2.0.0-rc.1",
"@ angular / core": "2.0.0-rc.1",
"@ angular / http": "2.0.0-rc.1",
"@ angular / platform-browser": "2.0.0-rc.1",
"@ angular / platform-browser-dynamic": "2.0.0-rc.1",
"systemjs": "0,19.31",
"core-js": "^ 2.4.0",
"отражать-метаданные": "^ 0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^ 0.6.12"
},
"devDependencies": {
"машинописный текст": "^ 1.8.10",
"typings": "^ 1.0.4",
"одновременно": "^ 2.2.0",
"lite-server": "^ 2.2.2"
}

И вот зависимости, вызывающие указанную ошибку:
"dependencies": {
"@ angular / common": "2.0.0-rc.4",
"@ angular / compiler": "2.0.0-rc.4",
"@ angular / core": "2.0.0-rc.4",
"@ angular / http": "2.0.0-rc.4",
"@ angular / platform-browser": "2.0.0-rc.4",
"@ angular / platform-browser-dynamic": "2.0.0-rc.4",
"systemjs": "0,19.31",
"core-js": "^ 2.4.0",
"отражать-метаданные": "^ 0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^ 0.6.12"
},
"devDependencies": {
"машинописный текст": "^ 1.8.10",
"typings": "^ 1.0.4",
"одновременно": "^ 2.2.0",
"lite-server": "^ 2.2.2"
}

RC2 тоже не работает!

Просто вопрос, но есть ли способ получить дополнительную информацию об ошибке? Например, было бы неплохо узнать, что такое «выражение», когда в сообщении об ошибке «выражение меняется с« истина »на« ложь »!.

У меня также возникла такая же проблема после обновления с RC1 до RC4. И то, что я понял, это связано с функцией ngOnInit в моем компоненте. Если я закомментирую эту функцию, сообщение об ошибке исчезнет, ​​и все будет работать нормально. Есть предположения?

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

но люди говорили, что они все еще сталкиваются с этой проблемой в новом RC ...

В среду, 13 июля 2016 г., в 00:52, Виктор Берше [email protected]
написал:

Закрыт № 6005 https://github.com/angular/angular/issues/6005.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/angular/angular/issues/6005#event -720794445 или отключить звук
нить
https://github.com/notifications/unsubscribe/AAgIEFEVZmE0M53XxNpzAYg9hJT_E_viks5qVAyGgaJpZM4G4J_s
.

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

Больше информации:

Оказывается, из-за вызова async внутри ngOnInit возникает эта ошибка. Если я закомментирую код асинхронного вызова или перемещу этот фрагмент кода в конструктор, все будет работать нормально.

@ ammar91
Назовите это после изменений:
changeDetectionRef.detectChanges ()

@ zigzag95 Да, это действительно обходной путь, но делать это кажется супер-хакерским. Я ожидал, что фреймворк, подобный angular, справится с этим более изящно, а не заставит нас вручную запускать собственный механизм обнаружения изменений.

В моем случае это происходит, когда я подписываюсь на эмиттер событий angular в app.component.ts чтобы показать и скрыть индикатор выполнения. Все было хорошо с RC1, но с RC4 все было хорошо.

Вот репродукция, http://plnkr.co/edit/jEtfUrQdc4sJBySj5kWN?p=preview
Нажмите на ссылку «Герои» и выберите одного из героев для редактирования, и вы увидите сообщение об ошибке.
См. Изменения в app.component.ts и hero.service.ts

Привет, @vicb , спасибо за обновление. Расскажите, какие действия были предприняты? Вы имеете в виду, что это будет исправлено в следующем выпуске?

Еще одно простое альтернативное решение, которое сработало для меня, - вернуть значение как наблюдаемое и задержать выдачу значений на 10 мс. В моем случае исключение произошло со значением счетчика
<app-spinner *ngIf="spinner"></app-spinner>

  this.eventService.toggleSpinnerAnnounced$.subscribe(
      (show: boolean) => this.spinner = show
    );

это сработало для меня:

private spinner = new Subject<boolean>();
toggleSpinnerAnnounced$ = this.spinner.asObservable().delay(10); // This  delay() is important

announceSpinnerToggle(show: boolean) {
        this.spinner.next(show);
    }

Это сработало для вас, потому что вы используете задержку, и это не связано с наблюдаемым.
У вас будет такое же поведение при использовании stettimeout.

@Jarvens, пожалуйста, перестаньте публиковать этот комментарий в неподходящих местах.

Проблемы GitHub предназначены для отчетов об ошибках и запросов функций.
Если у вас возникнут вопросы в службу поддержки, используйте другие каналы, например, указанные в разделе

В вашем комментарии недостаточно информации для диагностики вашей проблемы.

К вашему сведению: я получил эту ошибку из-за расширения chrome ng-inspector for AngularJS (расширение angular 1, альтернатива batarang)

Это безумие! После прочтения всего потока проблема в режиме разработки была устранена, так как отключил ng-Inspector для AngularJS, как говорит @ KarlGustav-unimicro.

С учетом сказанного ChangeDetectorRef.detectChanges() также работал у меня, но чувствовал себя действительно хакерским.

@ pkozlowski-opensource,
я до сих пор не знаю, почему indicatorStyle() будет вызываться при изменении одного из входных данных,
вы можете дать больше объяснений?
Если я реализую ngDoCheck в _progress-bar component_ без установки ChangeDetectionStrategy.OnPush в родительском компоненте,
я обнаружил, что ngDoCheck выполнение два раза,
я знаю, почему будет выполнен первый,
но я действительно запутался во втором ngDoCheck ...

http://plnkr.co/edit/myX2Alx9jie2q0FDIME7?p=preview

@LiTiang ,

я до сих пор не знаю, почему будет вызываться indicatorStyle () при изменении одного из входных данных,
вы можете дать больше объяснений?

Поскольку indicatorStyle() привязан к [ngStyle] в представлении, он всегда будет вызываться при запуске детектора изменений. Это произойдет независимо от того, изменились ли входы на самом деле или нет.

я обнаружил, что ngDoCheck выполняется два раза,
я знаю, почему будет выполнен первый,
но я действительно запутался во втором ngDoCheck ...

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

Вариант setTimeout ()

ОБНОВЛЕНИЕ: CPU сошел на 100% без companionHeightПоследнее сравнение: AFAIK Обновления были рекурсивными!

ОБНОВЛЕНИЕ 2: Пример Plunker

Я хотел, чтобы высота динамического блока <ul> контролировала высоту <img>, которую я привязал к «companionHeight».

Так зло ... Но следующее работает с использованием Observable.

Вот элемент <ul>, высота которого отслеживается:

<ul class="title-list-ul" #listul (window:resize)="setCompanionHeight(listul)">

Вот контролируемый элемент <img>:

<img class="title-list-companion-img" [src]="getCompanionImageURL()" [height]="companionHeight"/>

Вот компоненты, которые взаимодействуют между собой:

import { Component, OnInit, AfterViewChecked, ElementRef } from '@angular/core';  // redacted
import { Observable } from 'rxjs';

@Component({
  selector: 'resume-title-list',
  templateUrl: './title-list.component.html',
  styleUrls: ['./title-list.component.scss']
})
export class TitleListComponent implements OnInit, AfterViewChecked {

  private error: Object;
  private companionHeight: number = 0;
  private companionHeightLast: number = 0;

   // Lots of irrelevant stuff like ngInit redacted for simplicity.

  constructor(private elementRef: ElementRef) { }  // redacted, mine is more complicated.

  setCompanionHeight(listElement: any) {
    let clientRect = listElement.getBoundingClientRect();
    if (clientRect) {
      this.companionHeight = clientRect["height"];
    }
  }

  // window::resize only happens when the window is resized: This is an initialization 
  // function that sets the initial size of the image... Without it the image height is 
  // initially zero and the image is not shown. 
  // The height was not correct in ngAfterViewInit, so I used ngAfterViewChecked instead.

  ngAfterViewChecked() {
    let ularray = this.elementRef.nativeElement.getElementsByClassName("title-list-ul");
    if (ularray && ularray.length > 0) {
        let h = ularray[0].getBoundingClientRect().height;
        if (h && h != this.companionHeightLast) {
          this.companionHeightLast = h;
          Observable
          .of(h)
          .delay(10)
          .subscribe(h => this.companionHeight = h,
                     error => this.error = error);
        }
    }
  }
}

Комментарии по закрытым вопросам могут быть не прочитаны членами команды Angular.
А как насчет того, чтобы задать вопрос в одном из этих каналов. УЧАСТВОВАТЬ - есть вопрос или проблема? с Plunker для воспроизведения?

У меня была такая же проблема с:

<div *ngIf="isLoading">
   <app-some-viewchild></app-some-viewchild>
</div>

Используйте [скрытый] вместо * ng, если решите проблему.

Я тоже столкнулся с этой проблемой. Наконец, я обнаружил, что объект инициации по умолчанию совпадает с объектом ngModle.

установка changeDetection: ChangeDetectionStrategy.OnPush в декораторе @Component исправила это для меня

@elvismercado спасибо, решает мою проблему в 2.1.1!

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

Если у меня есть вход, который имеет фокус, а затем удаляю его из DOM (условие ngIf), возникает ошибка «Выражение было изменено после того, как оно было проверено» (только если вход имеет связанную группу форм).
Вот плункер с проблемой:
https://plnkr.co/edit/dooRvC1gY1WEcaNdshoP?p=preview
Спасибо!

Итак, какое здесь решение?

Это вызовет изменение любого входного значения в ngOnInit.

@coli
просто завернуть в

setTimeout(()=>{
 ///your code here
}, 1);

У меня есть комбинация дочерних компонентов, которые необходимо предварительно загрузить, когда пользователь хочет отредактировать существующий объект.
Я боролся с этой проблемой в течение нескольких часов, пока мне не удалось исправить ее, используя сообщение @drewlio выше.

Ввести _changeDetectionRef:

    constructor(
        private _changeDetectionRef: ChangeDetectorRef) {
    }

И затем сразу после того, как вы сделали ваш вызов изменения, обнаружите изменения.
Это помогло мне.

    setSizeFromCtrl() {
        console.log("setSizeFromCtrl");
        if (this.sizeFromList && this.tradeProfile && this.tradeProfile.SizeFrom && this.sizeFromCtrl) {
            this.sizeFromCtrl.select(String(this.tradeProfile.SizeFrom));
            this._changeDetectionRef.detectChanges();
            console.log("setSizeFromCtrl DONE");
        }
    }

    setCentreTypeCtrl() {
        console.log("setCentreTypeCtrl");
        if (this.centreTypeList && this.tradeProfile && this.tradeProfile.centreTypeList && this.centreTypeCtrl) {

            for (let i of this.tradeProfile.centreTypeList) {
                this.centreTypeCtrl.select(i.value);
            }
            this._changeDetectionRef.detectChanges();
            console.log("centreTypeCtrl DONE");
        }
    }


Обратите внимание, что у меня была такая же проблема, но с другой (похожей?) Причиной и другими решениями.

  • Наше приложение Angular - https://github.com/GeoscienceAustralia/GNSS-Site-Manager , имеет реактивные формы модели, которые вложены и построены из нескольких компонентов в ngOnInit() . Некоторые из этих форм свернуты с ngIf в шаблоне
  • Данные также считываются в ngOnInit() и применялись с theModelForm.patchValue(data)
  • Эта ошибка появлялась, когда одна из свернутых форм была развернута. Это связано с тем, что DOM не был построен, потому что форма была создана в ngOnInit() которая не срабатывала, пока не была развернута. Выньте patchValue() и проблема исчезла
  • Мы придумали два решения
  • Перед patchValue() запустите this._changeDetectionRef.detectChanges(); . И измените ngIf на [hidden] чтобы форма и DOM были полностью построены. Обратной стороной этого является затраты времени и памяти на создание полной формы и связанной с ней модели DOM (это может не быть проблемой во многих приложениях, но это было для нас, поскольку у нас есть гигантская форма).
  • Лучшее решение - применить patchValue() (или setValue() если данные и поля равны 1: 1) в компонентах, и, таким образом, это происходит только тогда, когда форма создается в ngOnInit() .

Я еще не зафиксировал эти изменения (22.03.17).

Поэтому не думаю, что это решение всех спасет.
Но у меня появление данной ошибки сопровождалось созданием нового элемента класса. Затем добавляем его в массив, который выводится через * ngFor.
Я решил эту проблему, добавив в свой класс конструктор, который заполнил поля, необходимые для отображения в шаблоне значений по умолчанию (нули, пустые строки)

export class Task {
    task_id: number;
....
    constructor() {
        this.task_name = '';
        this.task_desc = '';
        this.task_percent = 0;
  addNewTask():void{
    let newTask = new Task();
    this.tasksList.push(newTask);
  }

task_name & task_desc & task_percent я показываю в шаблоне. Если хотя бы одно из перечисленных полей не инициализировано в конструкторе, я получаю аналогичную ошибку.

+1

Решение AerisG222 работает

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

ngAfterViewInit() : void {
    // your code

    this._changeDetectionRef.detectChanges();
}

this._changeDetectionRef.detectChanges () работает, но в моем случае это вызовет другие проблемы. Я просто оборачиваю код внутри функции setTimeout (), она ее решает.

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

@Toxicable Извините, наверное, я не прояснил, я не использую this._changeDetectionRef.detectChanges (); Вместо этого я помещаю исходный код в setTimeout ().

@GuofuHuang, если все, что вы помещаете в setTimeout вызывает CD, и вы запускаете это на крючке жизненного цикла, возможно, вы вызываете бесконечные циклы CD. Решение - не вносить изменения, которые вызывают компакт-диск во время запуска компакт-диска.

@Toxicable Даже я установил 0?

@GuofuHuang, если значение 0 вызывает компакт-диск, тогда да

@Toxicable Я просто нашел эту ссылку http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful , в ней говорится, что setTimeout 0 - это что-то вроде паузы / выхода в C, я не Не знаю, вызовет ли это какой-нибудь компакт-диск, но теперь он отлично работает в моем. Если не это решение, есть ли у вас лучшее решение для этой проблемы?

@GuofuHuang Я не знаю, что делает pause / yield в C, но в JS он помещает обратный вызов в конец очереди событий. Мое решение такое же, как указано выше: решение не вносить изменения, которые вызывают компакт-диск во время запуска компакт-диска.

settimeout - это решение
Параметр ms указывать не нужно и я подожду одну галочку

@ zigzag95 @GuofuHuang посмотрите этот пример, чтобы узнать, почему setTimeout не является решением
https://plnkr.co/edit/dv8K9EvVQLG59Gxsl3oI?p=preview

@Toxicable Спасибо, но мой случай сильно отличается от этого, и я не вижу бесконечного цикла. Но это определенно хороший пример, помогающий мне лучше понять angular.

@GuofuHuang На самом деле этого не произойдет в вашем случае, потому что вы делаете это в ngAfterViewInit который вызывается только один раз. Я хотел сказать, что с помощью этого метода можно вызвать бесконечный цикл, поэтому его опасно использовать. Это то, что показывает plunkr.

@moutono Твои уловки мне помогли! Большое спасибо

Поскольку проблема связана с запуском обнаружения изменений, выполнение обещания также может работать, потому что ngZone monkey также исправляет обещания. Это сработало для меня:

ngAfterViewInit() {
  Promise.resolve().then(() => your_code_here);
}

Да, setTimeout работает, но мне не понравилось это исправление, в моем случае это было вызвано тем, что я менял значение в EventEmitter.
Решение было изменить
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>();
к
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>(true);

странно, правда?
Что ж, это правда означает, что вечерний асинхронный
https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html

есть ли решение этого? Почему закрыто?

Мне нужно очищать кеш каждый раз

в моем случае я заменял заглушку изображения при загрузке изображения, мне пришлось поместить его в setTimeout

@intergleam @ wasa4587 @ caroso1222 @tandu @ AerisG222 @ Drew-Моор @robwormald @ svi3c @ pkozlowski-@pcroc с открытым исходным кодом @zoechi @stefankoru @bennadel @bryanforbes @Necroskillz @drewlio @ElsewhereGames @zoechi @ user414 @ е-унц

Это ошибка, возникающая при разработке. На рабочем сервере работает нормально.

@smartHasmukh это ошибка только в режиме разработки, поэтому неудивительно.
Вы все равно должны это исправить.

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

@smartHasmukh Я тоже находил это неудобным. Например, я подключаюсь к событиям навигации и затем отправляю событие основному компоненту, чтобы показать загрузчик. И в каждом компоненте я затем скрываю этот загрузчик после получения данных с сервера (то есть в рамках подписки). Хорошо. Но в одном компоненте я получил только некоторые данные из «статического» источника, которые там не наблюдались, поэтому я просто попытался использовать ngOnInit, чтобы указать основному компоненту скрыть загрузчик. Потом, конечно же, я получил ошибку.

Хотя мой случай должен быть простым, это неправильный способ. Мне пришлось либо принять решение, в первую очередь, не показывать загрузчик для этого компонента (что могло бы стать более сложным, если бы у меня было больше таких компонентов) ... или также обработать скрытие загрузчика из моей службы данных , а не на уровне компонентов. Или, уродливое решение, заключалось бы в том, чтобы обернуть этот конкретный случай в setTimeout (). Потому что первоначальный подход был неправильным.

TL / DR:
Я уверен, что для вашего сценария также должен быть правильный способ, кроме уродливого исправления _setTimeout () _ (которое я _sadly_ выбрал в тот момент, но опять же, это очень простой сценарий, и я знаю, что происходит - но мне, возможно, придется изменить это в какой-то момент в будущем выпуске).
Вы можете попробовать StackOverflow для своего конкретного случая, расскажите подробнее. Должен быть способ.

Конечно, спасибо @MrCroft @tytskyi, и я сделаю это, мистер @zoechi, и я знаю, что это не удивительно. но я просто даю знать. ничего больше

@tytskyi

Тот факт, что это работает в производстве, случайно, вам следует проверить

Нет, в большинстве случаев я отвечаю на эту ошибку: «Да, я знаю, и это задумано». Многие компоненты в моих приложениях что-то загружают после инициализации и после получения новых значений в связанных переменных. Эта проблема - просто «известное безобразие» Angular, и никого это не волнует.

@ e-oz, если вы каким-либо образом влияете на родительское или одноуровневое состояние в любом из хуков жизненного цикла, это нарушает однонаправленный поток данных. Такие изменения следует вносить, когда состояние приложения стабилизируется, но не в процессе обнаружения изменений. Вот почему существуют уловки с микрозадачей, setTimeout 0 и т. Д.

@tytskyi успокойтесь со своим "следует", я

@ e-oz как это связано с HTTP-запросом. Ответ на HTTP-запрос вызывает обнаружение изменений, и вы не получите ошибку «Выражение изменилось ...».
Не могли бы вы предоставить дополнительную информацию?

@zoechi нет смысла тратить на это время, никто ничего не изменит, задача закрыта.

@ e-oz проблема была закрыта год назад, и тогда у команды Angular были совсем другие приоритеты (выпустить релиз), и тогда эта проблема не была препятствием.
Если вы считаете, что у вас есть веское дело, вам следует создать новый выпуск.

@zoechi Я думаю, что не ты

@ e-oz Ясно, ваши комментарии предназначены только для того, чтобы выразить ваше разочарование, и вы не заинтересованы в поиске решения. Пожалуйста, перестаньте тратить здесь время других на свои бесполезные комментарии.

если вы вызываете http, подпишитесь на свой компонент, просто добавьте ..
Promise.resolve().then(() => your_code_here);
или
myObservable.delay(10).subscribe(...)

Одно из двух решений решит вашу проблему

@vicb Не закрывать проблемы, которые не исправлены. Зачем ты это делаешь ?

По крайней мере, предложить какое-то исправление, но закрывать это недопустимо

@diegogarciaa ... а что именно не исправлено или неправильно с вашей точки зрения? Разговор ^^^ такой длинный, что трудно найти реальное ядро.

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

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

@diegogarciaa ... очень хорошо. Продолжайте, как указано выше, и вам везде будут рады.

@ mlc-mlapis Я не хочу, чтобы меня встречали там, где люди не умеют читать, и пытаюсь срать там, где не следует.

@diegogarciaa ... Я просто подумал, что у вас лично проблема, и похоже, что сейчас это не так. Реальность такова, что большинство проблем с Expression has changed after it was checked ... - это не ошибки, а просто неправильное понимание того, как работает CD.

@ mlc-mlapis ок ... давай разберемся

http://plnkr.co/edit/nm8OkrpZCIp4cvA6TbpO?p=preview

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

Но, например, если у меня есть ссылка на контейнер представления ... и я использую, например:

this.service.GetData (). subscribe (
response => this.component.instance.dataModel = ответ
);

Учтите, что dataModel используется как {{dataModel.Field}} в моем html

this.component - это динамический компонент, загружаемый при определенных событиях, как можно избежать ошибки? Что было бы правильным способом передать данные моему компоненту до того, как перехватчики жизненного цикла обнаружения изменений

@diegogarciaa ... да, это типичный пример, когда операции async и sync смешиваются и встречаются вместе на одном компакт-диске и его подтверждение в режиме разработки. Я не буду повторять объяснение из сообщения https://hackernoon.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4 , так что, возможно, попробуйте сначала его прочитать.

И посмотрите также https://hackernoon.com/here-is-how-to-get-viewcontainerref-before-viewchild-query-is-evaluated-f649e51315fb.

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

Скажем честно, я очень расстроен текущим статусом ... даже минимальные вещи в angular такие скучные и утомительные ... Я даже не могу дышать. Пошел на хуй

@diegogarciaa ... нет, это просто вспомогательное решение. Вы также можете использовать promise.then или setTimeout ... но рекомендуемым решением в этом случае, вероятно, является общая служба, поэтому вы не будете напрямую обновлять свойство динамического компонента через цикл CD и его подтверждение.

Или просто создайте экземпляр динамического компонента в тот момент, когда у вас будут данные. Таким образом, ваша подписка вызовет создание экземпляра динамического компонента.

Но что важно -> основная логика, почему происходит ошибка -> потому что однонаправленные изменения всегда должны течь сверху вниз по всему дереву, и после одного цикла CD есть подтверждение статуса, что принцип однонаправленности был соблюден.

Это «пошел на хуй» не было личным ... просто выражением моего разочарования.

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

protected loadPartialView(viewName: string, target: ViewContainerRef) : ComponentRef<any> {
        const factories = Array.from(this.resolver['_factories'].keys());
        const factoryClass = <Type<any>>factories.find((x: any) => x.name === viewName);
        const factory = this.resolver.resolveComponentFactory(factoryClass);
        return target.createComponent(factory);
}

В приведенном выше примере: я хотел бы сделать что-то вроде этого:

return target.createComponent(factory, dataSource);

Где мой источник данных будет доступен во время конструктора

Подобно redux, который использует объект для обработки источника данных, проходящего через компоненты, мы думаем о реализации инъекционного компонента, который обрабатывает данные за нас, чтобы мы могли получить его до перехватов жизненного цикла.

Diegogarciaa

Я не думаю, что данные должны быть доступны раньше ... динамический компонент по-прежнему является компонентом с @Input() и @Output() но вопрос в том, когда вы измените данные.

... данные должны быть доступны при загрузке компонента ...

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

export default class LazyLoadedModule {
    cmps: Map<{}, {}> = new Map();
    constructor() {
        this.cmps.set('first-component', FirstComponent);
        ...
    }
}

Что должно означать return target.createComponent(factory, dataSource); ? Потому что фактический API - это createComponent(componentFactory, index, injector, projectableNodes, ngModule) .

И, возможно, вам будет интересен новый модуль @ angular / cdk. Просто введите здесь: https://medium.com/@caroso1222/a -first-look-into-the-angular-cdk-67e68807ed9b.

Для чего это стоит и может ли это кому-то помочь, вместо использования setTimeout и поскольку использование ChangeDetectorRef.detectChanges() не сработало для меня, я закончил тем, что использовал NgZone.onStable и выполнил свой код подписавшись один раз на EventEmitter ...

constructor(
  private zone: NgZone,
) { }

ngAfterViewInit() {
  this.zone.onStable.first().subscribe(() => {
    // your code here
  });
}

Я не до конца осознаю последствия этого, но может ли это быть хуже, чем использование setTimeout ? Если у кого-то есть какие-либо комментарии по этому поводу, это было бы очень приятно!

Решение @ AerisG222 работает для меня

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

ngAfterViewChecked() : void {
    // your code
    this._changeDetectionRef.detectChanges();
}

это компонент html:

{{lastData.note [i] .date | date: 'dd.MM.yyyy'}} | {{lastData.note [i] .date | date: 'ЧЧ: мм'}}:# BFL15_200817 | {{lastData.status.name}} от {{lastData.note [i] .admin}}

Я получил сообщение об ошибке, если данных в массиве больше одного. Любое решение?

Это, безусловно, сложная проблема, но в некоторых случаях (особенно когда вы изменяете свойства ContentChild) ее можно решить, переместив логику в ngAfterContentInit () вместо ngAfterViewInit () или ngOnInit ()

Удивительно, как простые вещи могут вызвать такую ​​путаницу в angular

Не волнуйтесь, все тоже заметили 😕
image

@jakeNiemiec хромая работа, тролль, никто больше не ищет Angularjs
https://trends.google.com/trends/explore?date=all&q=Angular%20tutorial , React% 20tutorial
image

Да, я ожидал, что большему количеству людей потребуется гуглить "angular tutorial" от отчаяния, отсюда и первоначальный комментарий о "путанице".

Но не волнуйтесь, мы можем проверить npm для точной статистики использования: http://www.npmtrends.com/react-vs-@angular/cli -vs-vue-vs- @ angular / core
image
image

Просто сравните количество вопросов. Мне бы очень хотелось, чтобы angular стал лучше, но я подозреваю, что Vue.js передаст его в далеком будущем. Запрограммировав все три, я настоятельно рекомендую Vue разработчикам angular. Это как angular без шаблона.

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

@jakeNiemiec ... 50% создаваемых задач ошибочно помещены туда ... на самом деле это проблемы поддержки / знаний, и их там вообще не должно быть. Самое интересное, что большинство необходимых тем очень хорошо задокументировано в официальных документах + ответы основаны на знании JavaScript. Но вы знаете, люди не читают документы достаточно глубоко.

@HostBinding может сбивать с толку источником этой ошибки.

Рассмотрим простую привязку к компоненту, например @HostBinding('style.background') .

Это свойство проверяется обнаружением изменений * родительского * компонента, как если бы он «владел» им. С нашей точки зрения, мы хотим думать об этом как о дочернем компоненте, «владеющем» этим свойством.

Кажется, должен быть способ для компонента исключить свойства для проверки в этом случае? Или все сложнее?

Мне пришлось заставить мой родительский компонент запустить detectChanges (или добавить дополнительный div в дочерний элемент), чтобы избежать ошибки в случае, когда дочерний компонент просто менял свой собственный цвет фона (и никогда не делал этого где-либо еще) .

Более полное описание: https://stackoverflow.com/questions/43375532/expressionchangedafterithasbeencheckederror-explained/51662105#51662105

Вам просто нужно сделать что-нибудь, что угодно, что вызовет еще один раунд обнаружения изменений во время этого метода - испустить событие, что угодно. Обернуть его в тайм-аут (возврат в очередь на ng1 :-P) - это один из способов, который сработает, но мне кажется, что в ng2 очень беспорядочно.

В угловом 4 это работает 4 me <3

Эта проблема была автоматически заблокирована из-за бездействия.
Пожалуйста, сообщите о новой проблеме, если вы столкнулись с аналогичной или связанной проблемой.

Узнайте больше о нашей политике автоматической блокировки разговоров .

_Это действие было выполнено автоматически ботом. _

Была ли эта страница полезной?
0 / 5 - 0 рейтинги