Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing the child component residing under ng-component with ViewChild in Angular

I have parent component, there is a ng-template section. Under this ng-template section there is a Child Component. Now I would like to access this child component with ViewChild decorator. After getting with ViewChild I want to execute a function of that child component. But it’s not working. The code is below:

<ng-template #mymodal let-modal>
  <div class="modal-header">
    <h4 class="modal-title" id="modal-basic-title">Bootstrap Modal</h4>
    <button type="button" class="close" aria-label="Close" (click)="modal.dismiss('Cross click')">
      <span aria-hidden="true">&times;</span>
    </button>
  </div>
  <div class="modal-body">
    <app-expense-head #child></app-expense-head>
  </div>
  <div class="modal-footer">
    <button type="button" class="btn btn-outline-dark" (click)="modal.close('Save click')">Ok</button>
    <button type="button" class="btn btn-outline-dark" (click)="onClickCancel()">Cancel</button>
  </div>
</ng-template>

TS file code

@ViewChild(ExpenseHeadComponent, { static: false }) childExpenseHead: ExpenseHeadComponent;

onClickCancel() {
    this.childExpenseHead.myAlert();    
  }
like image 509
mnu-nasir Avatar asked Oct 15 '22 22:10

mnu-nasir


2 Answers

You already added template reference in child using #child. So in template, you can access the public methods in child using this reference like below

 (click) ="child.myAlert()"
like image 93
Jobelle Avatar answered Oct 22 '22 14:10

Jobelle


It can work from the class code. See below example that is similar in structure to your code and notice the use of ngAfterViewInit and ViewChild:

See it working here.

HTML (parent component)

<ng-template #myTemplate>
  <hello name="{{ name }}"></hello>
</ng-template>
<button (click)="clickChild()">Call Child</button>

TS (parent component)

import { AfterViewInit, Component, EmbeddedViewRef, OnInit,  TemplateRef, VERSION, ViewChild, ViewContainerRef } from '@angular/core';
import { HelloComponent } from './hello.component';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit, AfterViewInit  {
  @ViewChild(HelloComponent, { static: false }) child: HelloComponent;
  @ViewChild('myTemplate', { static: false, read: TemplateRef }) myTemplate: TemplateRef<any>;
  name = 'Angular ' + VERSION.major;

  constructor(private viewContainerRef: ViewContainerRef) {}
  
  ngOnInit(): void {
  }

  ngAfterViewInit(): void {
    const embeddedViewRef = this.viewContainerRef.createEmbeddedView(this.myTemplate);

    embeddedViewRef.detectChanges();
  }

  clickChild(): void {
    this.child.myAlert();
  }
}

HTML and ts (child component)

import { Component, Input } from '@angular/core';

@Component({
  selector: 'hello',
  template: `<h1>Hello {{name}}!</h1>`,
  styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
  @Input() name: string;

  myAlert(): void {
    console.log('in hello component');
    alert('alert child');
  }
}
like image 1
Benny Avatar answered Oct 22 '22 12:10

Benny