How to force a component's re-rendering in Angular 2? For debug purposes working with Redux i'd like to force a component to re-render it's view, is that possible?
Rendering happens after change detection. To force change detection, so that component property values that have changed get propagated to the DOM (and then the browser will render those changes in the view), here are some options:
- ApplicationRef.tick() - similar to Angular 1's
$rootScope.$digest()
-- i.e., check the full component tree - NgZone.run(callback) - similar to
$rootScope.$apply(callback)
-- i.e., evaluate the callback function inside the Angular 2 zone. I think, but I'm not sure, that this ends up checking the full component tree after executing the callback function. - ChangeDetectorRef.detectChanges() - similar to
$scope.$digest()
-- i.e., check only this component and its children
You will need to import and then inject ApplicationRef
, NgZone
, or ChangeDetectorRef
into your component.
For your particular scenario, I would recommend the last option if only a single component has changed.
this is the first time I am facing an update not working in ng2
. The change detection strategy is default so i know i have not messed up with the change detection strategy. –
Virilism this
context in the POST callback. –
Jab pure:false
in the pipe. It works but it is way too expensive (inefficient) for my use case. –
Possing tx, found the workaround I needed:
constructor(private zone:NgZone) {
// enable to for time travel
this.appStore.subscribe((state) => {
this.zone.run(() => {
console.log('enabled time travel');
});
});
running zone.run will force the component to re-render
ChangeDetectorRef approach
import { Component, OnInit, ChangeDetectorRef } from '@angular/core';
export class MyComponent {
constructor(private cdr: ChangeDetectorRef) { }
selected(item: any) {
if (item == 'Department')
this.isDepartment = true;
else
this.isDepartment = false;
this.cdr.detectChanges();
}
}
I force reload my component using *ngIf.
All the components inside my container goes back to the full lifecycle hooks .
In the template :
<ng-container *ngIf="_reload">
components here
</ng-container>
Then in the ts file :
public _reload = true;
private reload() {
setTimeout(() => this._reload = false);
setTimeout(() => this._reload = true);
}
setTimeout()
. Now mine is working with a simple and lightweight solution! –
Atheism Other answers here provide solutions for triggering change detection cycles that will update component's view (which is not same as full re-render).
Full re-render, which would destroy and reinitialize component (calling all lifecycle hooks and rebuilding view) can be done by using ng-template
, ng-container
and ViewContainerRef
in following way:
<div>
<ng-container #outlet >
</ng-container>
</div>
<ng-template #content>
<child></child>
</ng-template>
Then in component having reference to both #outlet
and #content
we can clear outlets' content and insert another instance of child component:
@ViewChild("outlet", {read: ViewContainerRef}) outletRef: ViewContainerRef;
@ViewChild("content", {read: TemplateRef}) contentRef: TemplateRef<any>;
private rerender() {
this.outletRef.clear();
this.outletRef.createEmbeddedView(this.contentRef);
}
Additionally initial content should be inserted on AfterContentInit
hook:
ngAfterContentInit() {
this.outletRef.createEmbeddedView(this.contentRef);
}
Full working solution can be found here https://stackblitz.com/edit/angular-component-rerender .
ngAfterViewInit
. BTW, it interestingly is the only solution that worked for me when input's held the previous values despite form model was correct. This occurred when I was switching between routes differentiated by the :id
route. In the end I had to call the rerender
function every time that navigation ended. –
Modify ChangeDetectorRef.detectChanges()
is usually the most focused way of doing this. ApplicationRef.tick()
is usually too much of a sledgehammer approach.
To use ChangeDetectorRef.detectChanges()
, you'll need this at the top of your component:
import { ChangeDetectorRef } from '@angular/core';
... then, usually you alias that when you inject it in your constructor like this:
constructor( private cdr: ChangeDetectorRef ) { ... }
Then, in the appropriate place, you call it like this:
this.cdr.detectChanges();
Where you call ChangeDetectorRef.detectChanges()
can be highly significant. You need to completely understand the life cycle and exactly how your application is functioning and rendering its components. There's no substitute here for completely doing your homework and making sure you understand the Angular lifecycle inside out. Then, once you understand that, you can use ChangeDetectorRef.detectChanges()
appropriately (sometimes it's very easy to understand where you should use it, other times it can be very complex).
© 2022 - 2024 — McMap. All rights reserved.