Ich weiß, dass im Stack-Overflow bereits viele gleiche Fragen gestellt wurden, und habe verschiedene Lösungen ausprobiert, um den Laufzeitfehler zu vermeiden, aber keine davon funktioniert für mich.
Komponenten- und HTML-Code
export class TestComponent implements OnInit, AfterContentChecked {
@Input() DataContext: any;
@Input() Position: any;
sampleViewModel: ISampleViewModel = { DataContext: : null, Position: null };
constructor(private validationService: IValidationService, private modalService: NgbModal, private cdRef: ChangeDetectorRef) {
}
ngOnInit() {
}
ngAfterContentChecked() {
debugger;
this.sampleViewModel.DataContext = this.DataContext;
this.sampleViewModel.Position = this.Position;
}
<div class="container-fluid sample-wrapper text-center" [ngClass]="sampleViewModel.DataContext?.Style?.CustomCssClass +' samplewidget-'+ sampleViewModel.Position?.Columns + 'x' + sampleViewModel.Position?.Rows">
//some other html here
</div>
Bitte beachten Sie: Diese Komponente wird dynamisch mit DynamicComponentLoader geladen
Nach meiner Fehlersuche habe ich einige Probleme festgestellt
Zunächst wird diese untergeordnete Komponente dynamisch geladen, indem DynamicComponentResolver verwendet und die Eingabewerte wie folgt übergeben werden
ngAfterViewInit() {
this.renderWidgetInsideWidgetContainer();
}
renderWidgetInsideWidgetContainer() {
let component = this.storeFactory.getWidgetComponent(this.dataSource.ComponentName);
let componentFactory = this._componentFactoryResolver.resolveComponentFactory(component);
let viewContainerRef = this.widgetHost.viewContainerRef;
viewContainerRef.clear();
let componentRef = viewContainerRef.createComponent(componentFactory);
debugger;
(<IDataBind>componentRef.instance).WidgetDataContext = this.dataSource.DataContext;
(<IDataBind>componentRef.instance).WidgetPosition = this.dataSource.Position;
}
Selbst wenn ich das HTML meiner untergeordneten Komponente wie unten geändert habe, wird der gleiche Fehler angezeigt. Fügen Sie einfach ein eckiges ngclass-Attribut hinzu
<div class="container-fluid ds-iconwidget-wrapper text-center" [ngClass]="Sample">
</div>
Meine Datenbindung und alles funktionieren einwandfrei. Muss ich irgendetwas an der übergeordneten Komponente tun? Ich habe bereits alle Lebenszyklusereignisse in der untergeordneten Komponente ausprobiert
quelle
TestComponent
?this.renderWidgetInsideWidgetContainer();
vonngAfterViewInit
bisngOnInit
Antworten:
Der
ngAfterContentChecked
Lifecycle-Hook wird ausgelöst, wenn die Bindungsaktualisierungen für die untergeordneten Komponenten / Anweisungen bereits abgeschlossen sind. Sie aktualisieren jedoch die Eigenschaft, die als verbindliche Eingabe für diengClass
Direktive verwendet wird. Das ist das Problem. Wenn Angular die Validierungsphase ausführt, erkennt es, dass eine Aktualisierung der Eigenschaften aussteht, und löst den Fehler aus.Lesen Sie diese beiden Artikel, um den Fehler besser zu verstehen:
ExpressionChangedAfterItHasBeenCheckedError
Fehler wissen müssenÜberlegen Sie, warum Sie die Eigenschaft im
ngAfterViewInit
Lifecycle-Hook ändern müssen . Jeder andere zuvor ausgelöste LebenszyklusngAfterViewInit/Checked
funktioniert beispielsweisengOnInit
oderngDoCheck
oderngAfterContentChecked
.Um dies zu beheben, bewegen Sie sich
renderWidgetInsideWidgetContainer
zumngOnInit()
Lifecycle-Hook.quelle
ngAfterViewInit/Checked
?ngOnInit
oderngDoCheck
oderngAfterContentChecked.
Wenn es immer noch nicht funktioniert, erstellen Sie einen PlunkerSie haben zu sagen ,
angular
dass Sie die Inhalte aktualisiert , nachdemngAfterContentChecked
Sie importierenChangeDetectorRef
aus@angular/core
und CalldetectChanges
quelle
Wenn Sie
<ng-content>
mit verwenden, müssen*ngIf
Sie in diese Schleife fallen.Der einzige Ausweg, den ich fand, war die Umstellung
*ngIf
aufdisplay:none
Funktionalitätquelle
Zwei Lösungen:
quelle
ngAfterViewInit() { setTimeout(() => { this.renderWidgetInsideWidgetContainer(); }, 0); }
Das ist eine gute Lösung, um dieses Problem zu lösen.
quelle
Ich habe meinen Code in setTimeout eingewickelt und es hat funktioniert
quelle
* NgIf kann hier ein Problem verursachen, also verwenden Sie entweder display none css oder es ist einfacher, [hidden] = "! Condition" zu verwenden.
quelle
Ich hatte Probleme mit.
Das Problem hierbei ist, dass der aktualisierte Wert erst erkannt wird, wenn der nächste Änderungserkennungszyklus ausgeführt wird.
Die einfachste Lösung besteht darin, eine Änderungserkennungsstrategie hinzuzufügen. Fügen Sie diese Zeilen zu Ihrem Code hinzu:
quelle
Ich hatte das gleiche Problem beim Versuch, etwas das Gleiche wie Sie zu tun, und ich habe es mit etwas ähnlichem wie Richie Fredicsons Antwort behoben.
Wenn Sie createComponent () ausführen, wird es mit undefinierten Eingabevariablen erstellt. Wenn Sie danach diesen Eingabevariablen Daten zuweisen, werden die Dinge geändert und dieser Fehler in Ihrer untergeordneten Vorlage verursacht (in meinem Fall, weil ich die Eingabe in einer ngIf verwendet habe, die sich geändert hat, nachdem ich die Eingabedaten zugewiesen habe).
Die einzige Möglichkeit, dies in diesem speziellen Fall zu vermeiden, besteht darin, die Änderungserkennung zu erzwingen, nachdem Sie die Daten zugewiesen haben. In ngAfterContentChecked () habe ich dies jedoch nicht getan.
Ihr Beispielcode ist etwas schwer zu befolgen, aber wenn meine Lösung für Sie funktioniert, wäre es ungefähr so (in der übergeordneten Komponente):
Meins ist fast das gleiche, außer dass ich @ViewChildren anstelle von @ViewChild verwende, da ich mehrere Hostelemente habe.
quelle
Versuchen Sie dies, um Ihren Code in ngOnInit () aufzurufen.
quelle