4
votes

Please have a look at the Stackblitz Editor link. I've set up one angular application.

Brief working overview of the angular app

  • Two components i.e app-component and child-component
  • Initially, child component not display. There is a button in the parent app component when we click on the button, we enable one variable 'this.showChildComponent = true'.
  • child component controlled by the variable this.showChildComponent.
  • I'm using the 'firstParam' and 'secondParam' as a variable and sending these variables values to the child component.

Now, Please have a look at the issue

When we click on the button as I explained above, child component mounted and ngOnInit method will be called, you can also check the message on the console screen 'ngOnInit called: child component' but if I again click on the button, then the child component not re-render again and thus, ngOnInit method of child component not called.

// This method is defined in the app-component (parent) and it is called when user clicks on 
// button
showChild() {
    if (this.showChildComponent)
    {
      this.showChildComponent = false;
    }
    this.showChildComponent = true;
    // child component ngOnInit call when
    // I use the timer
    // setTimeout(()=> {this.showChildComponent = true;}, 10);
    this.firstParam = 'first param from parent';
    this.secondParam = 'second param from parent';
  }

// Parent component - app-component
<button (click)="showChild()">Click here to display the child component</button>

<div *ngIf="showChildComponent">
  <app-child-component
    [first_param]="firstParam"
    [second_param]="secondParam"
  ></app-child-component>
</div>

As you can see in the code, if I use the setTimeout then child component ngOnInit method will be called whenever I click on the parent component button. But I don't want to use the timer here, what is the alternative solution to resolve this issue? whenever user clicks on the button, ngOnInit method of child component should be call.

4
what you want to achieve in child component when user clicks on button again ?YogendraR
@YogendraR whenever the user clicks on the button, ngOnInit method of child component should be called.Shubham
that's what I am asking, what you want to do inside ngOnInit with every button click. What is the use case here ? As I can see, you don't want to destroy child either.YogendraR
@Shubham you have set it to false and then true before the change detection has had a chance to read that there is a change. This means that the child component will not be removed and then re-added. This is why it works by using a timeout, because the timeout will get executed after the change detection. If you really want the behavior to run in the ngOnInit then you would need to use a settimeout to wait for the component to be destroyed.jgerstle
@jgerstle thanks for your input and time. But is there an alternate approach to destroy the child component?Shubham

4 Answers

1
votes

Copied from comment to give a bit of reference for the answer:

You have set it to false and then true before the change detection has had a chance to read that there is a change. This means that the child component will not be removed and then re-added. This is why it works by using a timeout, because the timeout will get executed after the change detection. If you really want the behavior to run in the ngOnInit then you would need to use a settimeout to wait for the component to be destroyed.

Since it seems that you don't want to use the setTimeout, even though that's how I'd suggest doing it, you can force the change detection using one of the methods provided here. Here is a stackblitz fork from your original question, using the third approach.

1
votes

Try this one to toggle your component:

  showChild() {
    this.showChildComponent = !this.showChildComponent;
    this.firstParam = 'first param from parent';
    this.secondParam = 'second param from parent';
  }
0
votes

You need to add some additional condition to your if statement. Right now, the logic always assigns this.showChildComponent to true (even after you've assigned it to false). Change your showChild method to:

showChild() {
    if (this.showChildComponent)
    {
      this.showChildComponent = false;
    } else {
      this.showChildComponent = true;
    }
    // child component ngOnInit call when
    // I use the timer
    // setTimeout(()=> {this.showChildComponent = true;}, 10);
    this.firstParam = 'first param from parent';
    this.secondParam = 'second param from parent';
  }

You were previously always setting the showChildComponent attribute to true and never were destroying the child. Thus, it was never re-rendering.

0
votes

For this you can manually trigger the child component by using ChangeDetectorRef

Create an instance of ChangeDetectorRef and use like this below in app component.

this.changeDetectorRef.detectChanges();

Or Alternative way to achieve this is to use ngOnChanges, which will change everytime when you pass params as Input to child component. Here is a stackblitz fork by using ngOnChanges lifecycle hook.