dopatraman
dopatraman

Reputation: 13908

How do I re-render a component manually?

I'm a newcomer to Angular2, I'm used to the Angular 1 digest cycle, meaning if I update the scope of a view I can manually trigger a digest by calling $scope.$digest(). However, I'm not sure how to do this in Angular2, esp given that the new framework doesn't have the implicit data binding that the old version had.

Here's my problem. I have a route that loads a component when a url with a parameter is hit:

// Router
export const AppRoutes : RouterConfig = [
    {
    path: 'my/:arg/view',
    component: MyComponent  
    }
]

Then I have this component:

// Component
export class MyComponent {
    constructor(private route : ActivatedRoute,
      private r : Router) {
    let id = parseInt(this.route.params['value'].id);
    console.log(id);
    // do stuff with id
    }

    reloadWithNewId(id:number) {
        this.r.navigateByUrl('my/' + id + '/view');
    }
}

Lets say I navigate to url /my/1/view. It will call the constructor and the number 1 is logged. However, if I call reloadWithNewId with a new id, reloadWithNewIf(2), the constructor is not called again. How do I manually reload the component?

Upvotes: 27

Views: 97852

Answers (4)

Madhu Ranjan
Madhu Ranjan

Reputation: 17894

Constructor will not be called again when you are just updating the params. Because the Component class is already instantiated,

you can subscribe to params changes like below if you want to detect the change,

  constructor(route: ActivatedRoute) {
    route.params.subscribe(param => {
        let id = param['id '];
        // Do your stuff with id change.
    });
  }

Upvotes: 3

bersling
bersling

Reputation: 19242

I think the changeDetectorRef is the proper tool for this job:

HTML

<my-component *ngIf="!reloading"
              (loadNext)="onLoadNext()">
</my-component>

TS

  constructor(
    private cdr: ChangeDetectorRef
  ) { }

  onLoadNext() {
      this.reloading = true;
      this.cdr.detectChanges();
      this.reloading = false;
      this.cdr.detectChanges();
  }

Why would you want this, instead of "updating the model and the view updates itself", as in the answer that Günther provided? This way you're sure the component gets reinitialized and there aren't some left over values from before. That's why I find it cleaner to do it like this.

Example: https://stackblitz.com/edit/commatrainer-v1

Upvotes: 2

G&#252;nter Z&#246;chbauer
G&#252;nter Z&#246;chbauer

Reputation: 657078

There shouldn't be a need to reload the component. Just update the model and the view updates itself:

export class MyComponent {
    constructor(private route : ActivatedRoute,
      private r : Router) {}

    reloadWithNewId(id:number) {
        this.r.navigateByUrl('my/' + id + '/view');
    }

    ngOnInit() {
      this.sub = this.route.params.subscribe(params => {
         this.paramsChanged(params['id']);
       });
    }

    paramsChanged(id) {
      console.log(id);
      // do stuff with id

    }
}

Upvotes: 20

Germaniero
Germaniero

Reputation: 198

You can force angular2 to re-initialize component by navigating to some other url and then back to one you want.

Here is my simple workaround using Router class methods (reference: https://angular.io/docs/ts/latest/api/router/index/Router-class.html)

Component constructor:

constructor(private router: Router) {}

In template (example):

(click)="onTabChange(id)"

Then inside component class:

onTabChange() {
  if (this.router.navigated === false) {
    // Case when route was not used yet
    this.router.navigateByUrl(`/module/${id}`);
  } else {
    // Case when route was used once or more
    this.router.navigateByUrl(`/index`).then(
      () => {
        this.router.navigateByUrl(`/module/${id}`);
      });
  }
}

Upvotes: 14

Related Questions