41

I have a component inside another component, added by tag. At some point, i would like to reinitialize this sub-component, like the first it was invoke. Is there any way to do that?

2
  • 1
    What are you trying to do? There is no way to just tell a component to reinitialize itself. But there are ways to get it to reget new data for itself. If you could provide a bit more information, we can suggest some options for you. Commented Aug 1, 2017 at 16:19
  • The idea is to open the component as a modal, pre-loaded in each component that will open it. Of course, when the modal is closed, the component needs to be reinitilized for future calls. Commented Aug 1, 2017 at 16:46

7 Answers 7

23

You can write your own cleanup method. But faster way (but not trully convenient) is to use *ngIf. When value is false, component is completely removed (destroyed) from page. When it is back to true it goes via regular path constructor > ngOnInit, etc. Why it is not convenient?

  • it may look ugly
  • it may require from you to trigger change detection manually

.

reinitChildComponent(): void{
    this.childVisible = false;
    this.changeDetectorRef.detectChanges();
    this.childVisible = true;
    this.changeDetectorRef.detectChanges();
}
Sign up to request clarification or add additional context in comments.

2 Comments

This is the only correct answer (for me at least), coz that's exactly what I needed. It should have a thousand upvotes, at least. Angular should provide a more obvious mechanism to achieve this.
Does not seem to work for me in Angular 15. The component just disappears... As noted in an answer below, maybe the best approach in such cases is to use some kind of Subject and pass it as observable to the child component, so you can notify it when to reset.
18

You can re initialize component using *ngIf.

<mychild *ngIf="flag"></mychild>

You can re initialize by making the flag false and true.

1 Comment

Can use a ChangeDetectorRef to trigger detection of the toggling without setTimeout e.g. this.flag = false; this.cd.detectChanges(); this.flag = true;.
17

Add a public method in your child component say init (). Then add an id to your child component in your parent component html.

<my-child #myChild></my-child>

Then you can get the child component like:

@ViewChild('myChild') private myChild: MyChildComponent;

From that you can call the init() method which has all initialization logic of component.

4 Comments

This make sense for me +1
The idea is not to write all the things i need to reinitialize the component
There is no direct approach to reinitialize the component. You'll have to use one the workarounds specified in the answers.
Here is a link to a similar problem: stackoverflow.com/a/45433354/1791913
11

I ran into this problem when doing a test page that would render components for visual inspection.

I tried the ngIf approach mentioned in another answer, but it didn't work without using a setTimeout which seems more like a hack.

Turns out that ngFor is perfect for this. You just use an array with a single empty object. Each time you modify the array then ngFor will re-create the inner component.

public reset: any[] = [{}];

public onRecreate() {
    this.reset[0] = {};
}

Then in your template

<my-child-component *ngFor="let r of reset"></my-child-component>

<button (click)="onRecreate()">Reset</button>

2 Comments

sounds interesting, but ugly as hell.. haha. I will try this approach
ugly and if any other programmer saw it they wouldn't know why. make sure to add lots of comments :)
3

Usually you should just move the child-component's initializing logic from it's constructor / ngOnInit into it's ngOnChanges hook. But if you really need to re-initialize a component due to whatever reasons (usually if the represented object has changed), just use an *ngFor, which iterates over an array with only that specific reason as element:

<child-component [child]="child" *ngFor="let child of [child]"></child-component>

You can use a trackBy Function, if you want the component to re-initialize only if a certain property of the represented object has changed.

Comments

1

usually the best practice, in this case, is to create Behovire Subject and pass it to the component as @input()

then you can fire any action by calling behoviresubjects.next('hi')

ex:

in your parent component

import { BehaviorSubject } from 'rxjs';

brodCastChnage: BehaviorSubject<any> = new BehaviorSubject(null);

and when you need to notify the child component about something :

this.brodCastChnage.next('something');

in HTML of the parent as well

<my-child [onChange]="brodCastChnage"></my-child>

in child component

      @Input() onChange;

      ngOnInit() {
        this.onChange.subscribe(res=>{
        console.log('i received',res)
       });
     }
  • don't forget to unsubscribe on destroy

3 Comments

This does not reinitialize component. Plus your answer is full of typos.
@PatrykWlaź this is the old answer now you can use "ChangeDetectionStrategy.OnPush" and then each time you change the component inputs, components will re-render
The question is not about simple rerender but about whole reinitialization; in other words - how to make component go through every lifecycle event again, like it did at the moment of creation. OnPush strategy doesn't change that (even when using this strategy, onInit won't run again when input properties change). A.Tim answer works
-2

Here is a good example, how to call child component from parent component:

I call child component's function in to my parent component like this:

<cp-file-manager [(ngModel)]="container" name="fileManager"[disableFiles]="true" [disableDocId]="id" [newFolderId]="newFolderId"></cp-file-manager>

Here you can see how to call child component function from parent component ts file:

import { Component, OnInit, ViewChild  } from '@angular/core';
import { FileManagerComponent } from '../../../../shared/components/file-manager/file-manager.component'

@ViewChild(FileManagerComponent) fileManager: FileManagerComponent;

doSomething() { //this is parent component function
            this.fileManager.openFolder(); //openFolder-is child component function
    }

additional info: http://learnangular2.com/viewChild/

1 Comment

The URL doesn't display the additional info.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.