Search code examples
angularprimengsidebarangular14

In PrimeNG 14, how do I invoke a function in a child component when its parent p-sidebar opens?


I'm using PrimeNG 14 and Angular 14. I have a p-sidebar with a child component in it

<p-sidebar [(visible)]="isDisplayed" [showCloseIcon]="true" position="right">
  <app-add-edit-form [model]="myObj"></app-add-edit-form>
</p-sidebar>

In my add-edit-form.service.ts file, I have this

export class AddEditFormComponent
  implements OnInit
{
  ngOnInit(): void {
    this.resetForm();
  }

  private resetForm() {
    ...
  }

But when my panel opens, "ngOninit" is not called, and I would like my "resetForm" function called whenever the sidebar panel opens with my child component. How do I do this?


Solution

  • The ngOnInit lifecycle hook only runs:

    [...] once, after the first ngOnChanges(). ngOnInit() is still called even when ngOnChanges() is not (which is the case when there are no template-bound inputs).

    So most probably your component is not being destroyed/recreated when the p-sidebar is hidden/shown. ngOnInit() is called the first time the component is added to the template and then never again.


    There are two ways you could call your resetForm() method when the p-sidebar opens:

    1. Using a template variable to access the instance of <app-add-edit-form> from which resetForm() could be made available:
    <p-sidebar (onShow)="addEditForm.resetForm()">
      <app-add-edit-form #addEditForm></app-add-edit-form>
    </p-sidebar>
    
    export class AddEditFormComponent {
      
      // Note this must be public to be accessible in the template above.
      public resetForm() {
        ...
      }
    }
    
    1. Passing the variable you're using to show/hide the p-sidebar to your <app-add-edit-form> as an @Input and using the ngOnChanges() lifecycle hook to detect when to reset your form.
    <p-sidebar [(visible)]="isDisplayed">
      <app-add-edit-form [showing]="isDisplayed"></app-add-edit-form>
    </p-sidebar>
    
    export class AddEditFormComponent implements OnChanges {
    
      @Input() showing: boolean;  
    
      ngOnChanges(changes: SimpleChanges) {
        if (changes.showing
            && changes.showing.previousValue === false
            && changes.showing.currentValue === true) {
          this.resetForm();
        }
      }
    
      // Note this can be private again.
      private resetForm() {
        ...
      }
    }
    

    I don't recommend it, but there technically is a third way that most closely matches your approach. It will, however, involve the overhead of destroying/recreating the component each time the p-sidebar changes state:

    1. Using the ngIf structural directive to destroy/recreate your component when the variable you're using to show/hide the p-sidebar changes:
    <p-sidebar [(visible)]="isDisplayed">
      <app-add-edit-form *ngIf="isDisplayed"></app-add-edit-form>
    </p-sidebar>
    
    export class AddEditFormComponent implements OnInit {
    
      // This is now called each time the sidebar opens
      // because this component is recreated each time.
      ngOnInit() {
        this.resetForm();
      }
    
      private resetForm() {
        ...
      }
    }