How to force a component's re-rendering in Ang

2019-01-03 01:20发布

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?

4条回答
太酷不给撩
2楼-- · 2019-01-03 02:01

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.

查看更多
Root(大扎)
3楼-- · 2019-01-03 02:06

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

查看更多
爷的心禁止访问
4楼-- · 2019-01-03 02:12

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 .

查看更多
萌系小妹纸
5楼-- · 2019-01-03 02:14

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

}
查看更多
登录 后发表回答