Angular: AUSNAHME: Der Ausdruck hat sich nach der Prüfung geändert.

Erstellt am 18. Dez. 2015  ·  147Kommentare  ·  Quelle: angular/angular

Hilfreichster Kommentar

Dies ist kein Fehler, sondern ein Feature des Dev-Modus, der wie vorgesehen funktioniert. Das Aufrufen von enableProdMode( ) - siehe aktualisiertes Plunk beim Bootstrapping der App verhindert das

Das heißt, es wird aus gutem Grund geworfen: Kurz gesagt, nach jeder Runde der Änderungserkennung führt der Entwicklungsmodus sofort eine zweite Runde durch, um zu überprüfen, ob sich seit dem Ende der ersten keine Bindungen geändert haben, da dies darauf hindeutet, dass Änderungen verursacht werden durch die Änderungserkennung selbst.

In Ihrem Plunk haben Sie die Bindung [attr.spinner]=isLoading und isLoading ändert sich als Ergebnis Ihres Aufrufs von this.load() , was geschieht, wenn ngAfterViewInit gefeuert wird, was geschieht als Teil der anfänglichen Änderungserkennungsrunde. Das an sich ist jedoch nicht problematisch - das Problem ist, dass this.load() eine Bindung ändert, aber keine neue Runde der Änderungserkennung auslöst, was bedeutet, dass diese Bindung erst in einer zukünftigen Runde der Änderungserkennung aktualisiert wird.

Alle 147 Kommentare

Ich war mit einem ähnlichen Problem konfrontiert und scheint darauf zurückzuführen zu sein, wie ein Kind initialisiert wird und wie ein Elternteil das Kind als Teil seines Initialisierungsprozesses aktualisieren könnte. Ich habe ein ähnliches Beispiel mit einer hässlichen Problemumgehung mit Zone: http://plnkr.co/edit/GI45u805pnFUtFeORnxn?p=preview , wobei die Problemumgehung wie folgt aussieht:

Konstruktor(private _zone : NgZone) { }

ngAfterViewInit() : void {
this._zone.overrideOnTurnDone(() => {
this.child.title = 'Titel vom Elternteil';
});
}

Dies ist kein Fehler, sondern ein Feature des Dev-Modus, der wie vorgesehen funktioniert. Das Aufrufen von enableProdMode( ) - siehe aktualisiertes Plunk beim Bootstrapping der App verhindert das

Das heißt, es wird aus gutem Grund geworfen: Kurz gesagt, nach jeder Runde der Änderungserkennung führt der Entwicklungsmodus sofort eine zweite Runde durch, um zu überprüfen, ob sich seit dem Ende der ersten keine Bindungen geändert haben, da dies darauf hindeutet, dass Änderungen verursacht werden durch die Änderungserkennung selbst.

In Ihrem Plunk haben Sie die Bindung [attr.spinner]=isLoading und isLoading ändert sich als Ergebnis Ihres Aufrufs von this.load() , was geschieht, wenn ngAfterViewInit gefeuert wird, was geschieht als Teil der anfänglichen Änderungserkennungsrunde. Das an sich ist jedoch nicht problematisch - das Problem ist, dass this.load() eine Bindung ändert, aber keine neue Runde der Änderungserkennung auslöst, was bedeutet, dass diese Bindung erst in einer zukünftigen Runde der Änderungserkennung aktualisiert wird.

Ich muss meine Komponente in afterViewInit einrichten, weil ich ChildView , das hier initialisiert wird. Was ist der richtige Weg, um diese Änderung in isLoading vorzunehmen? Anruf an this.load um setTimeout umbrechen?

Sie müssen nur etwas tun, irgendetwas, das während dieser Methode eine weitere Runde der Änderungserkennung auslöst - ein Ereignis ausgeben, was auch immer. Es in ein Timeout zu packen (Warteschlangen-Flashback zu ng1 :-P) ist eine Möglichkeit, die funktionieren würde, fühlt sich aber in ng2 für mich super chaotisch an.

Es sieht nicht benutzerfreundlich aus. Ich denke an diese Methode als den Ort, an dem ich meine Komponenteninitialisierung abschließen kann, wenn ihre Kinder definiert sind, und jetzt stellt sich heraus, dass sie einige benutzerdefinierte Regeln hat. Ich denke, Sie sollten eine neue Änderungserkennungsrunde intern erzwingen, damit sie in ng2 vor dem Benutzer verborgen ist.

Könnten Sie hier ein repräsentativeres Beispiel für das, was Sie erreichen möchten, posten? Wenn es Ihr Bildspinner ist, verwenden Sie besser eine Standardbindung.

@AerisG222 dito für dich. Gibt es einen Grund, warum Sie keine einfache Bindung verwenden können, um dies zu erreichen? Das Überschreiben des Zonenverhaltens wird normalerweise nicht empfohlen.

@robwormald Ja, in diesem Fall könnte ich die Eigenschaftsbindung durchführen. Der reale Fall, den ich habe, beinhaltet auch eine andere Eigenschaft, die etwas komplizierter ist - ein Array von benutzerdefinierten Objekten, aber auch das könnte sicherlich über die Eigenschaftsbindung festgelegt werden.

Ich nehme an, wenn es so etwas wie @ViewChild nicht gäbe, wäre es mir egal, da dies der einzig vernünftige Weg wäre, die Informationen weiterzugeben. Ich war jedoch sehr aufgeregt, @ViewChild damit ich damit auf Komponentenreferenzen im Code arbeiten konnte. Dies vereinfacht das Markup und ermöglicht mehr Kontrolle über Code, was bei Typoskript zusätzlich wertvoll ist, da es mehr Werkzeugunterstützung gibt (wie Intellisense und Überprüfung der Kompilierzeit). Es vereinfacht auch die Containerkomponente, da sie keine Membervariablen verfolgen muss, die nur als Status für das untergeordnete Element verwendet werden sollen.

Ein weiterer kleiner Punkt ist, dass Sie beim Durchsuchen einer Anwendung mit der Eigenschaftsbindungssyntax die Vorlage überprüfen müssen, um zu sehen, wer die Daten letztendlich konsumiert. Dies wäre offensichtlicher, wenn über Code verdrahtet.

Ich habe den Code bereinigt, um nur das zu zeigen, was für das Beispiel wichtig ist. Die Idee ist, den Spinner nur anzuzeigen, während das Bild geladen wird, und dann den Spinner zu entfernen und das Bild anzuzeigen. Das Bild wird nur geladen, wenn das Element auf dem Bildschirm sichtbar ist.

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>

Ich muss das Bild nicht im Host behalten, da es beim Einblenden der Animation beim Abschluss des Ladevorgangs die Hintergrundopazität des Hosts nicht beeinträchtigen sollte.

Ich habe ein möglicherweise verwandtes Problem mit einer verschachtelten Direktive.
http://plnkr.co/edit/myX2Alx9jie2q0FDIME7?p=preview
Hier binde ich an ngStyle in der progressBar.ts.
Ich protokolliere das Style-Objekt, bevor ich zurückkehre, um zu beweisen, dass sie gleich sind.
Ich bekomme auch die ExpressionChangedAfterItHasBeenCheckedException .

@svi3c Sie geben tatsächlich ein _unterschiedliches_ Objekt zurück. Jeder Funktionsaufruf gibt eine neue Objektinstanz zurück, die der vorherigen in Bezug auf Schlüssel/Werte, aber nicht in Bezug auf Instanzen/Referenzen „gleich“ ist.

Es gibt mehrere Möglichkeiten, mit dieser Situation umzugehen:

  • Werte in einer Objektinstanz aktualisieren, anstatt eine neue Kopie zurückzugeben
  • Verwenden der Strategie ChangeDetectionStrategy.OnPush , sodass Ihre Funktion nur aufgerufen wird, wenn sich eine der Eingaben ändert, z. B.: http://plnkr.co/edit/NWyVoTtkiAzqWJphLMbi?p=preview

Vielleicht möchten Sie https://github.com/ng-bootstrap/core/blob/master/src/progressbar/progressbar.ts als weiteres Beispiel für eine Progressbar-Direktive für ng2 (unter Verwendung von HTML / CSS von Bootstrap) überprüfen.

@pkozlowski-opensource Vielen Dank!
Ich habe nur https://angular.io/docs/ts/latest/guide/template-syntax.html#!#ngstyle gelesen und bin noch nicht über Strategien zur Änderungserkennung gestolpert. Das ist großartig! :)

@drew-moore:

Sie müssen nur etwas tun, irgendetwas, das während dieser Methode eine weitere Runde der Änderungserkennung auslöst - ein Ereignis ausgeben, was auch immer.

Können Sie sagen, was der _richtige_ und _einfachste_ Weg ist, die Änderungserkennung in ngAfterViewInit erneut auszulösen - vorausgesetzt, es wird nur eine zu aktualisierende Eigenschaft benötigt. ApplicationRef.tick() funktioniert hier nicht, da dies die Ausnahme 'ApplicationRef.tick wird rekursiv aufgerufen' verursacht; Das Ausgeben eines Ereignisses, nur um eine Änderungserkennung auszulösen, fühlt sich falsch an (und hat bei mir nicht funktioniert), ebenso wie setTimeout .

Basierend auf den Kommentaren hier scheint es eine ziemlich häufige Anforderung zu sein, eine gebundene Eigenschaft in ngAfterViewInit zu aktualisieren (aufgrund einer Abhängigkeit von einer untergeordneten Komponente), sodass Angular 2 eine einfache Möglichkeit dafür zu fehlen scheint.

Wenn das Aktualisieren einer gebundenen Eigenschaft in ngAfterViewInit die _falsche_ Sache ist, was ist die Alternative?

Hier ist eine schnelle:

Herausforderung:
Legen Sie die Höhe des dom-Elements (über eine bestimmte Formel) basierend auf seiner gerenderten Breite fest.

Erwartung:
Wenn das Element gerendert wird, rufen Sie die Breite ab und berechnen Sie basierend darauf seine Höhe.

Wirklichkeit:
setTimeout?!

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

@Birowsky Plunker?

@zoechi Hier ist ein Beispiel: http://plnkr.co/edit/MML5uHEFQdL0k0TA5HtY

Sie können den setTimeout in app/app.component.ts#21 im ngAfterViewInit Lebenszyklus-Hook umschalten.

Ich bin auch auf etwas Ähnliches gestoßen, als ich versuchte, die Methode writeValue( newValue ) eines benutzerdefinierten ngModel valueAccessor zu implementieren. Wenn ich versuche, den newValue auf die Komponente anzuwenden, wird mir mitgeteilt, dass sich der Wert geändert hat (auf schlechte Weise). Wie Sie alle festgestellt haben, "behebt" es das Einpacken in ein setTimeout(); aber nicht auf eine gute weise.

Ich habe ein anderes Beispiel . Es ist etwas einfacher, indem ein @HostBinding() eingerichtet wird und von einem QueryList informiert wird.

Genauso wie mein Problem #5950.

Hier einige Empfehlungen, wie Sie dies sauber tun können.
http://stackoverflow.com/questions/34827334/triggering-angular2-change-detection-manually

Ich schließe jedoch immer noch setTimeout weil ich keinen von ihnen dazu bringen konnte, das zu tun, was ich brauche. Es sieht so aus, als ob ich am Ende eines Rückrufs ChangeDetectorRef.detectChanges() und die CD auslösen könnte.... Verpasse ich etwas? Vielleicht hilft es einem von euch.

Ich verwende die HTML5-Medienquellenerweiterungen, um einen Audiokontext basierend auf einem Videoelement zu erstellen, daher ist die Verwendung von @ViewChild erforderlich. Basierend auf dem Audiokontext versuche ich, einige Informationen anzuzeigen, z. B. die Anzahl der Kanäle. Allerdings bin ich auch auf dieses Problem gestoßen. Wie kann man das richtig umgehen?

@ElsewhereGames Schwer zu sagen, ohne

@zoechi Ich habe keinen tatsächlichen Fehler zu melden, den Kommentar von createMediaElementSource .

Ich habe im Januar mit einem _ngModel_-Problem gepostet. Jetzt bin ich wieder mit dem _ViewChildren_-Problem zurück. Im Gegensatz zu einigen dieser anderen Beispiele versuche ich jedoch nicht , in meiner Demo tun . Das heißt, meine Controller haben null Logik - es sind alle Metadaten und Ansichtsbindungen. Daher bin ich mir nicht sicher, wo ich überhaupt Spielraum habe, um _Dinge durcheinander zu bringen_:

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

Ein ähnliches Problem tritt auf, könnte aber den Code neu schreiben, um es zu umgehen. Ich habe mit @bennadel Post viel gelacht, also danke. Teilen Sie etwas von dem Gefühl mit früheren Problemen, die ich hatte, bei denen die intelligente Änderungserkennung entweder nicht intelligent genug, zu intelligent oder zu intelligent für mich war:-)

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

Bisher gab es immer eine Möglichkeit, es zu umgehen, aber ich werde es hier noch einmal vorschlagen, zumindest könnte der Änderungserkennungsmechanismus mehr Dokumentation gebrauchen. @bennadel Dein Problem erinnert mich an ein anderes Problem,

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

Um dies zu beheben, wurde vorgeschlagen, einen zusätzlichen Lebenszyklus-Hook OnBeforeBinding/OnBeforeRendering hinzuzufügen. Es scheint, als würde diese Lösung auch Ihr Problem lösen.

@tandu ersetze einfach ngAfterViewInit durch ngOnInit

@tandu, es spielt keine Rolle, wann Ihr Spinner startet (

@e-oz https://github.com/angular/angular/issues/6005#issuecomment -165951692 Ich greife auf untergeordnete Grenzen zu, um zu erkennen, ob ich mit dem Laden von Bildern beginnen soll.

@tandu und Sie könnten all diese Überprüfung in den Code der untergeordneten Komponente verschieben (er wäre in ngAfterViewInit der untergeordneten Komponente legitim) und das Ereignis an die übergeordnete Komponente senden, wenn isLoading geändert werden soll.

@e-oz Ich definiere die Komponente als #holder in html: <image-holder #holder></image-holder> . Es gibt also keine js-Datei dafür.

also erstellen Sie es, sonst muss ngAfterViewInit nicht verwendet werden, wenn View
hat keine echten Komponenten als Kinder - nichts wird gerendert.

Am Sonntag, den 13. März 2016 um 15:18 Uhr schrieb tandu [email protected] :

@e-oz https://github.com/e-oz Ich definiere die Komponente als #holder in html:

Halter>

. Es gibt also keine js-Datei dafür.


Antworten Sie direkt auf diese E-Mail oder zeigen Sie sie auf GitHub an
https://github.com/angular/angular/issues/6005#issuecomment -195963389.

Ich kann auch element.getElementsByTagsName oder ähnliche Methoden verwenden und nicht ChildComponent verwenden. Es gibt definitiv Workarounds. Mir geht es gut mit setTimeout Fix. Das Problem ist, dass der Methodenname darauf hindeutet, dass er verwendet werden kann, um eine Logik zu definieren, die möchte, dass untergeordnete Komponenten initialisiert und an die Komponente gebunden werden, aber die Methode sagt nicht, dass sie mitten im Änderungserkennungszyklus ausgeführt wird, und daher haben wir lange Thread von Beschwerden von verschiedenen Leuten.

@tandu Da stimme ich dir absolut zu, es ist eine sehr ärgerliche Einschränkung.

Für das, was es wert ist, habe ich meine ursprüngliche Problemumgehung wie folgt geändert, was sich wie ein vernünftiger Ansatz anfühlt. Vielleicht ist das für deine Situation einen Versuch wert:

    constructor(private _changeDetectionRef : ChangeDetectorRef) { }

    ngAfterViewInit() : void {
        // your code

        this._changeDetectionRef.detectChanges();
    }

Ich erhalte die gleiche Ausnahme bei der Verwendung der Formularvalidierung (erforderliche Eingabe). Bezogen auf dieses Problem?

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

@eivindr hatte einen kurzen Blick und ich hatte ngFormControl noch nie bei einer Eingabe gesehen, kann nicht sehen, warum oder was es bedeuten würde, da es auf das Formularelement gehen sollte, um es an eine Kontrollgruppe zu binden, und die einzelne Eingabe hätte eine entsprechende ngControl. Auf jeden Fall in deinem Plunker entfernen

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

und es behebt deinen Fehler.

Ich weigere mich, dieses Problem zu löschen :) Gestern konnte ich zeigen, dass mein Problem speziell mit Hostbindungen zusammenhängt , die von Eingabeeigenschaften abhängen:

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

Ich muss glauben, dass dies an dieser Stelle ein Fehler ist, da die Komponente zwei Dinge hat, die von der Eingabe abhängen - die Ansichtsvorlage und die Hostbindungen - und _nur eine davon_ die Änderungsausnahme verursacht. Wenn beide das Problem verursachen würden, würde ich etwas anderes denken; aber da nur einer von ihnen das Problem verursacht, muss es ein Bug sein, oder?

@eivindr Ich habe auch das gleiche Problem, wenn ich mit einem leeren Formular

@MarkPerryBV Nein, ich

@ user414 Wenn ich [ngFormControl] entferne ... gibt es keine "erforderliche" Validierung für die Eingabe.

@MarkPerryBV Ich habe eine vorerst) funktioniert. Ich musste ProdMode() aktivieren. Ich verwende ngIf für die Eingaben, daher musste ich auch eine ChangeDetectorRef.detectChanges () ausführen, nachdem die Eingabe gerendert wurde (wenn nicht, war die Eingabe trotz Inhalt ungültig).

Die Verwendung von enableProdMode() behebt nicht wirklich etwas - es maskiert nur das Symptom, indem es daran gehindert wird, die doppelte Überprüfung durchzuführen und Ihnen mitteilt, dass etwas wahrscheinlich nicht stimmt.

Der Fix von AerisG222 scheint besser zu sein als die Verwendung eines setTimeout . Ist es wirklich so, dass das beabsichtigte Verhalten darin besteht, die Änderungserkennung nach dem Aufruf von addControl() mit einem Validator manuell auslösen zu müssen?

Gleiches Problem hier nach dem Aufrufen von addControl(). Ich denke, addControl() sollte ChangeDetectionRef.detectChanges() aufrufen.

@CaptainCodeman Ich weiß - es war eine vorübergehende Problemumgehung.

Dies schlägt im Dev-Modus nicht mehr fehl, wenn ich [email protected] , zone verwende. [email protected]. Ich muss noch ChangeDetectionRef.detectChanges() aufrufen

@eivindr können Sie Ihren plnkr auf den Beta17-Fix aktualisieren?
Ich verliere den Verstand darüber, ich weigere mich, mich enableProdMode() zu unterwerfen.

@AerisG222 Dein Ansatz funktioniert für mich!

Ist die Verwendung des von @AerisG222 geposteten Ansatzes ein guter Ansatz? Ja, es funktioniert, aber gibt es ein Gewissen, changeDetectionRef.detectChanges() manuell auszulösen?

Ich habe das gleiche Problem, wenn ich versuche, eine dynamische Formularvalidierung durchzuführen und das Formular dann zurückzusetzen. hier ist mein plunk

Schritte zum Reproduzieren. Senden Sie das Formular mit Ist Mitarbeiter geprüft. Überprüfen Sie nach der Aktualisierung des Formulars erneut Ist Mitarbeiter.

Ich verwende die changeDetectionRef.detectChanges() in der Submit-Funktion.

danke dafür @AerisG222 :)

Ich mag den ganzen setTimeout-Workaround nicht. Ich schlage folgendes vor:

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

Die Verwendung von ChangeDetectorRef.detectChanges ist nicht immer ein guter Ansatz. Beispiel warum:

Die übergeordnete Komponente ruft die öffentliche API der untergeordneten Komponenten während ihrer ngAfterViewInit . Dieser Aufruf ändert die Bindung des untergeordneten Elements. Das Aufrufen von detectChanges von Parent würde das Problem ebenfalls lösen, aber das bedeutet, dass Eltern wissen müssen, wann detectChanges nach welchem ​​API-Aufruf des Kindes aufgerufen werden muss. Sie werden feststellen, dass das Aufrufen von detectChanges in der Child-Methode, die die Bindung in diesem Fall ändert, nicht funktioniert, wenn Sie ChangeDetectionStrategy.OnPush möchten.

Ich bin auf diesen Fehler gestoßen, als ich Kinder über ViewContainerRef.createComponent() dynamisch hinzugefügt und dann die untergeordnete Instanz aktualisiert habe. Ich verwende RC2 (und versuche, keine abgeschriebenen Sachen zu verwenden).

Anfangs funktionierte alles gut (erstes Rendern), aber dann fügte ich eine Komponente hinzu, die neue Daten ausgeben würde. Dieses Ereignis wurde von der übergeordneten Komponente abgehört, die ihr Datenarray aktualisiert hat, wodurch die Änderungserkennung und die Auffüllung neuer dynamischer untergeordneter Komponenten ausgelöst wurde. Das Ereignis wurde durch ein Absenden eines Formulars ausgelöst. Wenn ich auf den Absenden-Button drücke, war alles in Ordnung. Wenn ich die Eingabetaste drücke, um die Übermittlung zu generieren, würde dies den Fehler erzeugen.

Ich habe ChangeDetectorRef.detectChanges() direkt nach der Erstellung und Aktualisierung der dynamischen Komponente hinzugefügt. Kein großes Problem, aber es scheint seltsam, dass das System, obwohl ich gerade eine neue Komponente zur Ansicht hinzugefügt habe, die Änderungserkennung für das Kind nicht automatisch auslöst.

@ aerisg222 Muss ich dies aufrufen._changeDetectionRef.detectChanges () Nach jeder Änderung der Eigenschaften der Kinder von den Eltern?

Nun, ich bin gerade auf dieses Problem gestoßen. Ich habe zwei Geschwisterkomponenten, die dasselbe Datenobjekt verwenden. Beide Objekte sollen die Datenquelle aktualisieren können. Die andere Quelle sieht tatsächlich die Änderung im Objekt, löst jedoch aus, dass sich der Ausdruck geändert hat, nachdem er überprüft wurde. Vorheriger Wert: 'wahr'. Aktueller Wert: 'false'

Das ist mir nach dem Upgrade von RC1 auf RC4 passiert

Hier gilt das gleiche. Begann dies nach dem Upgrade von RC1 auf RC4 wieder.

Vielleicht hätte die Änderung, die dies verursacht hat, als Breaking Change im Änderungsprotokoll kommuniziert werden sollen ... meine Sachen sind jetzt kaputt.

Wir müssen auf das Finale warten.
Ich habe aufgehört, untergeordnete Komponenten zu verwenden, weil das Aktualisieren externer Eigenschaften scheiße ist.
Ich dachte, dafür wäre Zonen hier...

Hier gilt das gleiche. Das dynamische Laden von Komponenten über ViewComponentRef scheint sich in RC2 und RC4 anders zu verhalten als in RC1

Hier sind meine Arbeitsabhängigkeiten:
"Abhängigkeiten": {
"@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",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^0.6.12"
},
"devDependencies": {
"typescript": "^1.8.10",
"typings":"^1.0.4",
"gleichzeitig": "^2.2.0",
"lite-server": "^2.2.2"
}

Und hier sind die Abhängigkeiten, die den erwähnten Fehler erzeugen:
"Abhängigkeiten": {
"@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",
"reflect-metadata": "^0.1.3",
"rxjs": "5.0.0-beta.6",
"zone.js": "^0.6.12"
},
"devDependencies": {
"typescript": "^1.8.10",
"typings":"^1.0.4",
"gleichzeitig": "^2.2.0",
"lite-server": "^2.2.2"
}

RC2 funktioniert auch nicht!

Nur eine Frage, aber gibt es eine Möglichkeit, mehr Informationen zu dem Fehler zu erhalten? Zum Beispiel wäre es schön zu wissen, was der "Ausdruck" ist, wenn der Fehler lautet "Ausdruck ändert sich von 'wahr' zu 'falsch'!.

Ich habe auch genau das gleiche Problem nach dem Upgrade von RC1 auf RC4. Und was ich herausgefunden habe, liegt an der Funktion ngOnInit in meiner Komponente. Wenn ich diese Funktion auskommentiere, ist die Fehlermeldung weg und alles funktioniert einwandfrei. Irgendwelche Gedanken?

Dieses Problem wird geschlossen, da es alt ist und Maßnahmen ergriffen wurden. Wenn das Problem weiterhin besteht, erstellen Sie ein neues Problem und füllen Sie die Problemvorlage mit allen erforderlichen Details aus . Vielen Dank

aber die Leute sagten, dass sie dieses Problem immer noch in neuen RC haben ...

Am Mittwoch, den 13. Juli 2016 um 00:52 Uhr, Victor Berchet [email protected]
schrieb:

Geschlossen #6005 https://github.com/angular/angular/issues/6005.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/angular/angular/issues/6005#event -720794445 oder stumm
der Faden
https://github.com/notifications/unsubscribe/AAgIEFEVZmE0M53XxNpzAYg9hJT_E_viks5qVAyGgaJpZM4G4J_s
.

Ja, ich habe gerade auf RC4 aktualisiert und keine einzige Änderung an einer meiner Komponenten vorgenommen, außer einen neuen Router zu konfigurieren, und bin auf dieses Problem gestoßen. In RC1 war alles gut, es scheint, als ob es das immer noch gibt.

Mehr Info:

Es stellt sich heraus, dass dieser Fehler aufgrund eines async Aufrufs innerhalb von ngOnInit auftritt. Wenn ich den asynchronen Aufrufcode auskommentiere oder diesen Codeabschnitt in den Konstruktor verschiebe, funktioniert alles einwandfrei.

@ammar91
Rufen Sie dies nach Änderungen auf:
changeDetectionRef.detectChanges()

@zigzag95 Ja, dies ist in der Tat eine Problemumgehung, aber es fühlt sich super umständlich an, dies zu tun. Ich würde erwarten, dass ein Framework wie angle dies eleganter handhabt, anstatt uns dazu zu zwingen, seinen eigenen Änderungserkennungsmechanismus manuell auszulösen.

In meinem Fall passiert es, wenn ich den Angular Event Emitter in app.component.ts abonniere, um die Fortschrittsleiste anzuzeigen und auszublenden. Mit RC1 war alles gut, aber mit RC4 brach es ein.

Hier ist das Repro, http://plnkr.co/edit/jEtfUrQdc4sJBySj5kWN?p=preview
Klicken Sie auf Heroes Link und wählen Sie einen der zu bearbeitenden Helden aus, und Sie werden den Fehler sehen.
Bitte beachten Sie die Änderungen in app.component.ts und hero.service.ts

Hey @vicb , danke für das Update. Können Sie uns sagen, welche Maßnahmen ergriffen wurden? Meinst du, dass dies in der nächsten Version behoben wird?

Eine andere einfache alternative Lösung, die für mich funktioniert hat, besteht darin, den Wert als beobachtbar zurückzugeben und die Ausgabe von Werten um 10 ms zu verzögern. In meinem Fall trat die Ausnahme mit dem Spinnerwert auf
<app-spinner *ngIf="spinner"></app-spinner>

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

das hat bei mir funktioniert:

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

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

Dies hat für Sie funktioniert, da Sie die Verzögerung verwenden und sie nicht mit beobachtbar zusammenhängt.
Sie werden das gleiche Verhalten haben, wenn Sie stettimeout verwenden.

@Jarvens bitte hör auf, diesen Kommentar an unangemessenen Orten zu posten.

GitHub-Probleme beziehen sich auf Fehlerberichte und Funktionsanfragen.
Für Support-Fragen nutzen Sie bitte andere Kanäle wie die unter BEITRAGEN - Haben Sie eine Frage oder ein Problem?

Ihr Kommentar enthält nicht genügend Informationen, um Ihr Problem zu diagnostizieren.

Zu Ihrer Information: Ich habe diesen Fehler wegen der Chrome-Erweiterung ng-inspector for AngularJS (Winkel-1-Erweiterungsalternative zu Batarang) erhalten.

Das ist verrückt! Nachdem ich den ganzen Thread gelesen hatte, wurde das Problem im Entwicklungsmodus behoben, indem ng-inspector für AngularJS deaktiviert wurde, wie @KarlGustav-unimicro sagt.

Damit hat ChangeDetectorRef.detectChanges() auch bei mir funktioniert, fühlte sich aber wirklich hacky an.

@pkozlowski-opensource,
Ich habe immer noch keine Ahnung, warum indicatorStyle() aufgerufen wird, wenn sich eine der Eingaben ändert,
kannst du mehr erklären?
Wenn ich ngDoCheck in der _Progress-Bar-Komponente_ implementiere, ohne ChangeDetectionStrategy.OnPush in der übergeordneten Komponente festzulegen,
Ich habe herausgefunden, dass ngDoCheck zweimal ausgeführt wird,
Ich weiß, warum der erste hingerichtet wird,
aber ich bin wirklich verwirrt über das zweite ngDoCheck ...

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

@LiTiang ,

Ich habe immer noch keine Ahnung, warum IndicatorStyle() aufgerufen wird, wenn sich eine der Eingaben ändert,
kannst du mehr erklären?

Da indicatorStyle() in der Ansicht an [ngStyle] gebunden ist, wird es immer aufgerufen, wenn der Änderungsdetektor ausgeführt wird. Dies geschieht unabhängig davon, ob sich die Eingaben tatsächlich geändert haben oder nicht.

Ich habe herausgefunden, dass ngDoCheck zweimal ausgeführt wird,
Ich weiß, warum der erste hingerichtet wird,
aber ich bin wirklich verwirrt über den zweiten ngDoCheck ...

Dies liegt höchstwahrscheinlich daran, dass, wie bereits in diesem Thread erwähnt, die Änderungserkennung im Dev-Modus immer zweimal ausgeführt wird. Dies geschieht, um sicherzustellen, dass wir keinen Code haben, der Bindungen während der Änderungserkennung ändert, was zu schwierigen Fehlern in der Produktion führen könnte.

Eine Variation von setTimeout()

UPDATE: CPU ging ohne CompanionHeight zu 100% durch. Letzter Vergleich: AFAIK Updates wurden rekursiv!

UPDATE2: Plunker-Beispiel

Ich wollte, dass die Höhe eines dynamischen <ul>-Blocks die Höhe eines <img> steuert, das ich an "companionHeight" gebunden habe.

So böse... Aber das Folgende funktioniert mit einem Observable.

Hier ist das <ul>-Element, dessen Höhe überwacht wird:

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

Hier ist das <img>-Element, das gesteuert wird:

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

Hier sind die Komponentenmethoden, die interagieren:

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);
        }
    }
  }
}

Kommentare zu geschlossenen Problemen können von Angular-Teammitgliedern möglicherweise nicht gelesen werden.
Wie wäre es, wenn Sie eine Frage in einem dieser Kanäle posten. BEITRAGEN - Sie haben eine Frage oder ein Problem? mit einem Plunker zu reproduzieren?

Ich hatte das gleiche Problem mit:

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

Verwenden Sie stattdessen [hidden] *ngIf, um das Problem zu lösen.

Dieses Problem habe ich auch kennengelernt. Schließlich habe ich festgestellt, dass das Standardinitionsobjekt mit dem ngModle-Objekt identisch ist.

Das Festlegen von changeDetection: ChangeDetectionStrategy.OnPush im @Component Dekorator hat es für mich behoben

@elvismercado danke, löst mein Problem in 2.1.1!

Ich hatte eine untergeordnete Komponente, die sich auf einen von der übergeordneten Vorlage übergebenen Wert stützte, wobei die untergeordnete Vorlage diese Ausnahme auslöste, wenn sich der übergeordnete Wert änderte. Das Hinzufügen Ihres Vorschlags zur untergeordneten Komponente führt dazu, dass die Änderungserkennung nicht ausgeführt wird, bis der geänderte Wert an die untergeordnete Komponente übertragen wird, wodurch verhindert wird, dass die Erkennung vorzeitig ausgeführt wird, nehme ich an?

Wenn ich eine Eingabe mit Fokus habe und diese dann aus dem DOM entferne (ngIf-Bedingung), tritt der Fehler "Ausdruck hat sich nach der Überprüfung geändert" auf (nur wenn der Eingabe eine Formulargruppe zugeordnet ist).
Hier ist ein Plunker mit dem Problem:
https://plnkr.co/edit/dooRvC1gY1WEcaNdshoP?p=preview
Vielen Dank!

Also, was ist hier die Lösung?

Das Ändern eines beliebigen Eingabewerts in ngOnInit löst dies aus.

@coli
einfach einwickeln

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

Ich habe eine Kombination von untergeordneten Komponenten, die vorab geladen werden muss, wenn ein Benutzer eine vorhandene Entität bearbeiten möchte.
Ich habe stundenlang mit diesem Problem gekämpft, bis ich es mit dem obigen @drewlio- Post beheben konnte.

Injizieren Sie _changeDetectionRef:

    constructor(
        private _changeDetectionRef: ChangeDetectorRef) {
    }

Und dann direkt nach der Änderung rufen Sie "Detectchanges" auf.
Das hat bei mir den Trick gemacht.

    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");
        }
    }


Beachten Sie, dass ich das gleiche Problem hatte, aber eine andere (ähnliche?) Ursache und andere Lösungen.

  • Unsere Angular-App – https://github.com/GeoscienceAustralia/GNSS-Site-Manager , verfügt über modellreaktive Formulare, die in ngOnInit() verschachtelt und über mehrere Komponenten hinweg erstellt werden. Einige dieser Formulare werden mit einem ngIf in der Vorlage minimiert
  • Die Daten werden auch in einem ngOnInit() eingelesen und wurden mit einem theModelForm.patchValue(data)
  • Dieser Fehler trat auf, als eines der minimierten Formulare erweitert wurde. Dies hängt damit zusammen, dass das DOM nicht erstellt wurde, weil das Formular in ngOnInit() , das erst nach der Erweiterung ausgelöst wurde. Nimm die patchValue() und das Problem war weg
  • Wir haben zwei Lösungen gefunden
  • Führen Sie vor dem patchValue() ein this._changeDetectionRef.detectChanges(); . Und ändern Sie ngIf in [hidden] damit das Formular und das DOM vollständig erstellt sind. Die Kehrseite davon ist der Zeit- und Speicheraufwand, da das komplette Formular und das zugehörige DOM erstellt werden (dies mag in vielen Apps kein Problem sein, war es aber für uns, da wir ein riesiges Formular haben).
  • Die bessere Lösung besteht darin, die patchValue() (oder setValue() wenn die Daten und Felder 1:1 sind) in die Komponenten zu übernehmen und geschieht daher nur, wenn das Formular in ngOnInit() .

Ich habe diese Änderungen noch nicht festgeschrieben (22.3.17).

Ich glaube also nicht, dass diese Entscheidung alle retten wird.
Aber bei mir wurde das Auftreten des gegebenen Fehlers von der Bildung des neuen Elements der Klasse begleitet. Fügen Sie es dann dem Array hinzu, das über *ngFor ausgegeben wird.
Ich habe dieses Problem gelöst, indem ich meiner Klasse einen Konstruktor hinzugefügt habe, der die Felder auffüllte, die für die Anzeige der Standardwerte (Nullen, leere Zeilen) in der Vorlage erforderlich sind.

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 Ich zeige in der Vorlage an. Wenn mindestens eines der aufgelisteten Felder im Konstruktor nicht initialisiert ist, erhalte ich einen ähnlichen Fehler.

+1

AerisG222-Lösung funktioniert

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

ngAfterViewInit() : void {
    // your code

    this._changeDetectionRef.detectChanges();
}

this._changeDetectionRef.detectChanges() funktioniert, aber es wird in meinem Fall andere Probleme verursachen. Ich schließe den Code einfach in die Funktion setTimeout () ein, sie löst es.

@GuofuHuang dies zu tun, ist eine Möglichkeit, das Problem zu vermeiden, es nicht zu beheben, was manchmal zu unendlichen Änderungserkennungszyklen führen kann

@Toxicable Entschuldigung, wahrscheinlich habe ich nicht klargestellt, dass ich das nicht verwende._changeDetectionRef.detectChanges(); Stattdessen schließe ich meinen Quellcode in setTimeout() ein.

@GuofuHuang Wenn alles, was Sie in setTimeout eingeben, eine CD verursacht und Sie diese auf einem Lebenszyklus-Hook ausführen, ist es möglich, dass Sie unendliche CD-Zyklen verursachen. Die Lösung besteht darin, keine Änderungen vorzunehmen, die eine CD während eines CD-Laufs verursachen

@Toxicable Sogar ich habe es 0 gesetzt?

@GuofuHuang, wenn die Einstellung auf 0 eine CD verursacht, dann ja

@Toxicable Ich finde gerade diesen Link, http://stackoverflow.com/questions/779379/why-is-settimeoutfn-0-sometimes-useful , er sagt, dass setTimeout von 0 so etwas wie Pause/Yield in C ist. Ich weiß nicht, ob es eine CD verursacht, aber jetzt funktioniert es perfekt in meiner. Wenn nicht diese Lösung, haben Sie eine bessere Lösung für dieses Problem?

@GuofuHuang Ich weiß nicht, was Pause / Ertrag in C bewirkt, aber in JS wird der Rückruf an das Ende der Ereigniswarteschlange gestellt. Meine Lösung ist wie oben: Die Lösung besteht darin, keine Änderungen vorzunehmen, die CD während eines CD-Laufs verursachen

settimeout ist die Lösung
Sie müssen den ms-Parameter nicht angeben und ich warte einen Tick

@zigzag95 @GuofuHuang Sehen Sie in diesem Beispiel, warum setTimeout nicht die Lösung ist
https://plnkr.co/edit/dv8K9EvVQLG59Gxsl3oI?p=preview

@Toxicable Danke, aber mein Fall unterscheidet sich stark von diesem und ich sehe keine Endlosschleife. Aber dies ist definitiv ein gutes Beispiel, das mir hilft, mehr Winkel zu verstehen.

@GuofuHuang Tatsächlich wird es in Ihrem Fall nicht passieren, weil Sie es in ngAfterViewInit tun, das nur einmal aufgerufen wird. Mein Punkt war, dass es mit dieser Methode möglich ist, eine Endlosschleife zu verursachen, daher ist die Verwendung gefährlich. Das zeigt der plunkr.

@moutono Deine Tricks haben mir geholfen! Super danke 😄

Da es sich bei dem Problem um das Auslösen einer Änderungserkennung handelt, kann das Auflösen eines Versprechens auch funktionieren, da ngZone-Affen auch Versprechen patchen. Dieser hat bei mir funktioniert:

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

Ja, setTimeout funktioniert, aber ich mochte diesen Fix nicht, in meinem Fall wurde er verursacht, weil ich den Wert eines EventEmitter geändert habe
Die Lösung war Veränderung
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>();
zu
private generalSubscriber: EventEmitter<any> = new EventEmitter<any>(true);

verrückt oder?
Nun, das bedeutet wahr, der Ereignisemitter ist asynchron
https://angular.io/docs/ts/latest/api/core/index/EventEmitter-class.html

gibt es dafür eine lösung? Warum ist es geschlossen?

Ich muss jedes Mal den Cache leeren

In meinem Fall habe ich beim Laden eines Bildes einen Bild-Stub ersetzt und musste ihn in ein setTimeout

@intergleam @wasa4587 @caroso1222 @tandu @AerisG222 @drew- moore @robwormald @svi3c @pkozlowski-opensource @pcroc @zoechi @stefankoru @bennadel @bryanforbes @Necroskillz @drewlio @ElsewhereGames @zoechi @user414

Es Fehler beim Entwickeln. Auf Produktionsserver funktioniert einwandfrei.

@smartHasmukh Es handelt sich nur um einen Fehler im Entwicklungsmodus, daher keine Überraschung.
Sie sollten es noch beheben.

Wenn dieser Fehler auftritt, unterbrechen Sie höchstwahrscheinlich den Datenfluss in eine Richtung. Das könnte so etwas sein wie das Ändern von Daten einer Komponente in den Geschwistern, das Ändern von Daten des Elternteils in den Lebenszyklus-Hooks der Kinder, vielleicht noch etwas mehr.
Diese ausgelöste Ausnahme ist kein Fehler, sondern hilft dem Entwickler, zu verstehen, dass der Vertrag für den Datenfluss in eine Richtung in irgendeiner Weise gebrochen ist. Die Tatsache, dass dies in der Produktion funktioniert, ist zufällig, Sie sollten überprüfen, wie Sie Ihre Daten in der Eltern-Kind-Kommunikation ändern, und im Entwicklungsmodus korrigieren.

@smartHasmukh Das fand ich auch früher unangenehm. Zum Beispiel hänge ich mich in Navigationsereignisse ein und gebe ein Ereignis weiter an die Hauptkomponente aus, um einen Loader anzuzeigen. Und in jeder Komponente verstecke ich dann diesen Loader, nachdem ich die Daten vom Server erhalten habe (also innerhalb eines Abonnements). Das ist in Ordnung. Aber in einer Komponente habe ich nur einige Daten von einer "statischen" Quelle erhalten, dort keine beobachtbaren, also habe ich einfach versucht, ngOnInit zu verwenden, um der Hauptkomponente mitzuteilen, dass sie den Loader ausblenden soll. Dann habe ich natürlich den Fehler.

Auch wenn mein Fall eine einfache Sache sein sollte, ist es nicht der richtige Weg. Ich musste entweder die Entscheidung treffen, den Loader für diese Komponente gar nicht erst anzuzeigen (was schwieriger werden könnte, wenn ich mehr solcher Komponenten hätte) ... oder auch den Loader vor meinem Datendienst ausblenden , statt auf Komponentenebene. Oder eine hässliche Lösung wäre, diesen einen bestimmten Fall in setTimeout() einzuschließen. Denn der anfängliche Ansatz war nicht der richtige.

TL/DR:
Ich bin mir sicher, dass es auch für Ihr Szenario einen geeigneten Weg geben muss, außer einem _setTimeout ()_ hässlichen Fix (den ich in diesem Moment _leider_ gewählt habe, aber andererseits ist es ein sehr einfaches Szenario und ich weiß, was ist dort weitergeht - aber vielleicht muss ich es irgendwann in einer zukünftigen Version ändern).
Sie könnten StackOverflow für Ihren speziellen Fall ausprobieren, geben Sie weitere Details an. Es muss einen Weg geben.

Klar Danke @MrCroft @tytskyi und ich werde es tun Herr @zoechi und ich weiß Es ist keine Überraschung. aber ich gebe nur Bescheid. nichts anderes

@tytskyi

Dass das in der Produktion funktioniert, ist Zufall, solltest du dir mal anschauen

Nein, in den meisten Fällen ist meine Antwort auf diesen Fehler "Ja, ich weiß, und es ist beabsichtigt". Viele Komponenten in meinen Apps laden etwas nach der Initialisierung und nachdem sie neue Werte in gebundenen Variablen erhalten haben. Dieses Problem ist nur "bekannte Hässlichkeit" von Angular und niemand kümmert sich darum.

@e-oz Wenn Sie den Eltern- oder Geschwisterstatus in einem der Lebenszyklus-Hooks irgendwie beeinflussen, wird der Datenfluss in eine Richtung unterbrochen. Sie sollten solche Änderungen vornehmen, wenn sich der Anwendungsstatus stabilisiert hat, aber nicht mitten in der Änderungserkennung. Deshalb gibt es diese Tricks mit Microtask, setTimeout 0 etc.

@tytskyi beruhige dich mit deinem "sollte", ich Anspruch nehmen als die anfängliche Stabilisierung. Sie werden mich nicht überzeugen, dass dieses Verhalten von Angular richtig ist, versuchen Sie es erst gar nicht.

@e-oz wie hängt das mit einer HTTP-Anfrage zusammen. Eine HTTP-Anfrageantwort verursacht eine Änderungserkennung und Sie erhalten nicht den Fehler "Ausdruck hat sich geändert ...".
Können Sie bitte mehr Informationen geben?

@zoechi es gibt keinen Grund Zeit damit zu verschwenden, niemand wird nichts ändern, Aufgabe ist geschlossen.

@e-oz das Problem wurde vor einem Jahr geschlossen und das Angular-Team hatte damals ganz andere Prioritäten (eine Veröffentlichung rausbringen) und dieses Problem war damals kein Blocker.
Wenn Sie der Meinung sind, dass Sie einen gültigen Fall haben, sollten Sie eine neue Ausgabe erstellen.

@zoechi Ich denke nicht, dass du entscheiden wirst, was ich tun soll. Ich kann ein neues Problem erstellen, muss es aber nicht. Bei allem Respekt, ich mag diesen "Du solltest"-Ton nicht.

@e-oz Ich sehe, Ihre Kommentare dienen nur dazu, Ihrer Frustration Luft zu machen, und Sie sind nicht daran interessiert, eine Lösung zu finden. Bitte hör auf, die Zeit anderer Leute hier mit deinen nutzlosen Kommentaren zu verschwenden.

Wenn Sie http aufrufen, abonnieren Sie Ihre Komponente, fügen Sie einfach hinzu..
Promise.resolve().then(() => your_code_here);
oder
myObservable.delay(10).subscribe(...)

Eine der beiden Lösungen wird Ihr Problem lösen

@vicb Beenden Sie das Schließen von Problemen, die nicht behoben wurden. Warum tust du das ?

Schlagen Sie zumindest einige richtige Korrekturen vor, aber das Schließen ist inakzeptabel

@diegogarciaa ... und was genau ist nicht behoben oder aus deiner Sicht falsch? Das Gespräch ^^^ ist so lang, dass es schwer ist, den eigentlichen Kern zu finden.

@mlc-mlapis Bei allem Respekt, ich bin nicht dein Lehrer, wenn du das Problem nicht lesen oder verstehen kannst, hör auf zu stören. Ich habe lange Minuten damit verbracht, den gesamten Inhalt zu lesen, ich empfehle dasselbe.

Die Haltung des kantigen Teams (nicht alle Teams, aber die hier schließen dieses Thema) scheint so unternehmerisch: Nicht blockieren (mein Gehalt), nicht in absehbarer Zeit reparieren.

@diegogarciaa ... sehr gut. Mach weiter wie oben und du bist überall willkommen.

@mlc-mlapis Ich möchte nicht willkommen sein, wo die Leute nicht lesen können und versuchen, Blödsinn zu machen, wo nicht.

@diegogarciaa ... ich dachte nur, dass du persönlich ein Problem hast und es sieht so aus, als ob es jetzt nicht stimmt. Und die Realität ist auch, dass die meisten Probleme mit Expression has changed after it was checked ... keine Fehler sind, sondern einfach nicht das richtige Verständnis dafür, wie CDs funktionieren.

@mlc-mlapis ok... lass es uns verstehen

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

In diesem Plunk kann ich verstehen, dass die Variable gebunden und überprüft wurde, als ngAfterViewInit aufgerufen wurde. Wenn sie also einen neuen Wert empfängt und keine neue Prüfrunde auslöst, werden die Ausnahmen ausgelöst

Aber zum Beispiel, wenn ich eine View-Container-Ref habe ... und ich zum Beispiel verwende:

this.service.GetData().subscribe(
Antwort => this.component.instance.dataModel = Antwort
);

Beachten Sie, dass dataModel als {{ dataModel.Field }} in meinem HTML verwendet wird

this.component ist eine dynamische Komponente, die bei bestimmten Ereignissen geladen wird, wie könnte man den Fehler vermeiden? Was wäre der richtige Weg, um die Daten an meine Komponente zu übergeben, bevor die Lebenszyklus-Hooks der Änderungserkennung

@diegogarciaa ... ja, dies ist ein typisches Beispiel, bei dem Async- und Sync-Vorgang gemischt werden und sich auf einer CD treffen und im Entwicklungsmodus bestätigt werden. Ich werde die Erklärung aus dem Beitrag https://hackernoon.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4 nicht wiederholen, also versuche vielleicht, sie zuerst zu lesen.

Und schauen Sie sich auch https://hackernoon.com/here-is-how-to-get-viewcontainerref-before-viewchild-query-is-evaluated-f649e51315fb an.

Der Artikel sagt also im Grunde, dass ich manuell eine Änderungserkennungsrunde aufrufen muss...

Seien wir ehrlich, ich bin sehr verärgert über den aktuellen Status... selbst die minimalen Dinge in eckigen sind so langweilig und ermüdend... Ich kann nicht einmal atmen. Fick dich

@diegogarciaa ... nein, es ist nur eine promise.then oder setTimeout ... aber die empfohlene Lösung in diesem Fall ist wahrscheinlich ein Shared Service, sodass Sie die Eigenschaft der dynamischen Komponente nicht direkt über den CD-Zyklus und ihre Bestätigung.

Oder erstellen Sie einfach eine Instanz der dynamischen Komponente in dem Moment, in dem Sie die Daten haben. Ihr Abonnement ruft also die Erstellung der dynamischen Komponenteninstanz auf.

Aber was ist wichtig -> die primäre Logik, warum der Fehler auftritt -> denn unidirektionale Änderungen sollten immer von oben nach unten durch den gesamten Baum fließen und nach einem CD-Zyklus gibt es eine Bestätigung des Status, dass das unidirektionale Prinzip eingehalten wurde.

Dieses "Fick dich" war nicht persönlich... nur um meiner Frustration Luft zu machen.

Wir verwenden ein Direktivenschema, um unsere Komponenten zu handhaben. Wir haben einen Helfer erstellt, der eine Komponente in eine Komponentenansichtsreferenz lädt, und wie wir wissen, müssen die Daten verfügbar sein, wenn eine Komponente geladen wird

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);
}

Im obigen Beispiel: Ich möchte so etwas machen:

return target.createComponent(factory, dataSource);

Wo meine dataSource zum Zeitpunkt des Konstruktors verfügbar wäre

Wie Redux, das ein Objekt verwendet, um Datenquellen zu verarbeiten, die Komponenten durchlaufen, denken wir darüber nach, eine injizierbare Komponente zu implementieren, die Daten für uns verarbeitet, damit wir sie abrufen können, bevor der Lebenszyklus einhängt.

diegogarciaa

Ich glaube nicht, dass Daten verfügbar sein müssen, bevor ... eine dynamische Komponente immer noch eine Komponente mit @Input() und @Output() aber die Frage ist, wann Sie die Daten ändern.

... die Daten müssen beim Laden einer Komponente verfügbar sein ...

Ich nehme an, dass Sie auch Komponenten aus trägen geladenen Modulen verwenden müssen, also verwende ich eine Map direkt in einem Modul, um die Möglichkeit zu haben, auf Komponenten nur mit String-Namen zuzugreifen.

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

Was return target.createComponent(factory, dataSource); bedeuten soll? Weil die tatsächliche API createComponent(componentFactory, index, injector, projectableNodes, ngModule) .

Und vielleicht wäre das neue @angular/cdk-Modul für Sie interessant. Hier einfach intro: https://medium.com/@caroso1222/a -first-look-into-the-angular-cdk-67e68807ed9b.

Was es wert ist und wenn es jemandem helfen kann, anstatt setTimeout und da die Verwendung von ChangeDetectorRef.detectChanges() bei mir nicht funktioniert hat, habe ich am Ende NgZone.onStable und meinen Code ausgeführt indem Sie sich einmal für die EventEmitter abonnieren ...

constructor(
  private zone: NgZone,
) { }

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

Ich bin mir der Konsequenzen nicht ganz bewusst, aber kann es schlimmer sein, als setTimeout ? Wenn jemand einen Kommentar zu diesem Thema hat, wäre es wirklich willkommen!

@AerisG222 Lösung funktioniert für mich

constructor(private _changeDetectionRef : ChangeDetectorRef) { }

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

Dies ist die HTML-Komponente:

{{ lastData.note[i].date | Datum : 'dd.MM.yyyy'}} | {{ lastData.note[i].date | Datum: 'HH:mm' }}:#BFL15_200817 | {{ lastData.status.name }} von {{lastData.note[i].admin}}

Ich habe den Fehler erhalten, wenn die Daten im Array mehr als eins sind. Irgendeine Lösung?

Dies ist sicherlich ein komplexes Problem, aber in einigen Fällen (insbesondere wenn Sie Eigenschaften eines ContentChild ändern) kann es gelöst werden, indem die Logik in ngAfterContentInit() anstelle von ngAfterViewInit() oder ngOnInit() verschoben wird.

Es ist erstaunlich, wie einfache Dinge im Winkel so viel Verwirrung stiften können

Keine Sorge, alle anderen haben es auch mitbekommen 😕
image

@jakeNiemiec lahmer Job, Troll, niemand sucht mehr Angularjs
https://trends.google.com/trends/explore?date=all&q=Angular%20tutorial ,React%20tutorial
image

Ja, ich würde erwarten, dass mehr Leute aus Verzweiflung "Angular Tutorial" googeln müssen, daher dieser erste Kommentar zu "Verwirrung".

Aber keine Sorge, wir können npm auf genaue Nutzungsstatistiken überprüfen: http://www.npmtrends.com/react-vs-@angular/cli -vs-vue-vs-@angular/core
image
image

Vergleichen Sie einfach die Anzahl der Probleme. Ich würde wirklich gerne sehen, dass eckiger wird besser, aber ich vermute, dass Vue.js es in ferner Zukunft bestehen wird. Nachdem ich alle 3 programmiert habe, kann ich Vue eckigen Entwicklern wärmstens empfehlen. Es ist wie eckig ohne die Boilerplate.

ok Antwort akzeptiert, ich bin mit diesen Statistiken vollkommen in Ordnung.
Ich kann mir vorstellen, dass es in Indien mehr Leute gibt, die PHP verwenden als Java auf der ganzen Welt. Es wäre ein Idiot, PHP für eine große Unternehmensanwendung zu verwenden, also solltest du manchmal dein eigenes Gehirn benutzen, das Leben wird besser

@jakeNiemiec ... 50% der erstellten Probleme werden fälschlicherweise dort platziert ... sie sind tatsächlich Support- / Wissensprobleme und sollten überhaupt nicht vorhanden sein. Der Spaß ist, dass die meisten der benötigten Themen in den offiziellen Dokumenten sehr gut dokumentiert sind + die Antworten basieren auf JavaScript-Kenntnissen. Aber wissen Sie, die Leute lesen die Dokumente nicht tief genug.

@HostBinding kann eine verwirrende Quelle für diesen Fehler sein.

Stellen Sie sich eine einfache Bindung für eine Komponente vor, z. B. @HostBinding('style.background') .

Diese Eigenschaft wird von der Änderungserkennung der *übergeordneten * Komponente überprüft, als ob sie ihr „gehört“. Aus unserer Sicht möchten wir es als die untergeordnete Komponente betrachten, die diese Eigenschaft „besitzt“.

Es scheint also eine Möglichkeit für eine Komponente zu geben, Eigenschaften für die Überprüfung in diesem Fall auszuschließen? Oder ist es komplizierter?

Ich musste meine übergeordnete Komponente detectChanges ausführen lassen (oder ein zusätzliches div im untergeordneten Element hinzufügen), um den Fehler zu vermeiden, wenn die untergeordnete Komponente einfach ihre eigene Hintergrundfarbe änderte (und dies nirgendwo anders tat). .

Vollständigere Beschreibung: https://stackoverflow.com/questions/43375532/expressionchangedafterithasbeencheckederror-explained/51662105#51662105

Sie müssen nur etwas tun, irgendetwas, das während dieser Methode eine weitere Runde der Änderungserkennung auslöst - ein Ereignis ausgeben, was auch immer. Es in ein Timeout zu packen (Warteschlangen-Flashback zu ng1 :-P) ist eine Möglichkeit, die funktionieren würde, fühlt sich aber in ng2 für mich super chaotisch an.

In Winkel 4, das funktioniert 4 mir <3

Dieses Problem wurde aufgrund von Inaktivität automatisch gesperrt.
Bitte reichen Sie ein neues Problem ein, wenn Sie auf ein ähnliches oder verwandtes Problem stoßen.

Lesen Sie mehr über unsere Richtlinie zum automatischen Sperren von Konversationen .

_Diese Aktion wurde automatisch von einem Bot ausgeführt._

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen