Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to communicate parent child component with click event

I have a Angular 8 application. And I have a Parent and child relationship.

So I have a function in a parent DossierCorrespondenceComponent, but the function has to be triggererd in the child component.

So I have this function in the parent:

@Input()  myGotoItem: Function;


gotoItem(index, type: string) {
    this.showingSingle = true;

    switch (type) {
      case 'correspondence': {
        this.single = this.correspondenceEntries[index];
        break;
      }
      case 'attachments': {
        this.single = this.attachmentEntries[index];
        break;
      }
      default: {
        break;
      }
    }
    this.showingSingle = true;
  }

And I try to call it in the child component DossierCorrespondenceListComponent like this :

 <tr class="dossier-correspondencerow" *ngFor="let entry of correspondenceEntries; let i = index" (myGotoItem)="gotoItem(i, entry.type)">

But nothing happens

So what I have to change?

But I have a other component DossierCorrespondenceAttachmentsComponent who also uses that function:

 <tr class="dossier-correspondencerow" *ngFor="let entry of attachmentEntries; let i = index" (click)="gotoItem(i, entry.type)">

So If I have to move the function gotoItem(index, type: string) to both the child components than I have duplicate code.

I have it now like this in parent component:

<ng-container *ngIf="correspondenceEntries">
    <app-dossier-correspondence-list [correspondenceEntries]="correspondenceEntries" (onClick)="gotoItem(i, entry.type)"> </app-dossier-correspondence-list>
  </ng-container>

and ts parent component:

gotoItem(index, type: string) {
    this.showingSingle = true;

    switch (type) {
      case 'correspondence': {
        this.single = this.correspondenceEntries[index];
        break;
      }
      case 'attachments': {
        this.single = this.attachmentEntries[index];
        break;
      }
      default: {
        break;
      }
    }
    this.showingSingle = true;
  }

and child component:

  <tbody class="dossier-tablebody">
          <tr class="dossier-correspondencerow" *ngFor="let entry of correspondenceEntries; let i = index" (click)="gotoItem(i, entry.type)">
            <td>{{ entry.date | date:"dd-MM-y" }}</td>
            <td>{{ entry.name }}</td>
          </tr>
        </tbody>



and ts child component:


export class DossierCorrespondenceListComponent implements OnInit {

  @Input()
  correspondenceEntries: DossierEntry[];

  @Output()
  onClick = new EventEmitter();

  @Input() showingSingle;

  constructor() { }

  ngOnInit() {
  }

  ngOnChanges(changes) { console.log(changes)}

  click() {
    this.onClick.emit();
  }


}

But then I get this error:

dossier-correspondence-list.component.html:13 ERROR TypeError: _co.gotoItem is not a function
    at Object.handleEvent (dossier-correspondence-list.component.html:13)
    at handleEvent (core.js:29733)
    at callWithDebugContext (core.js:30803)
    at Object.debugHandleEvent [as handleEvent] (core.js:30530)
    at dispatchEvent (core.js:20520)
    at core.js:28942
    at HTMLTableRowElement.<anonymous> (platform-browser.js:1009)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:423)
    at Object.onInvokeTask (core.js:26760)
    at ZoneDelegate.push../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:422)

and I changed this:

 click() {
    this.onClick.emit(true);
  }

dossier-correspondence-item.component.ts:51 ERROR TypeError: _co.gotoItem is not a function
    at Object.handleEvent (dossier-correspondence-item.component.ts:51)
    at handleEvent (core.js:29733)
    at callWithDebugContext (core.js:30803)
    at Object.debugHandleEvent [as handleEvent] (core.js:30530)
    at dispatchEvent (core.js:20520)
    at core.js:28942
    at HTMLTableRowElement.<anonymous> (platform-browser.js:1009)
    at 
like image 603
mightycode Newton Avatar asked Sep 06 '25 03:09

mightycode Newton


1 Answers

Parent component :

<child (onClick)="gotoItem()"></child>

gotoItem() {
    //do something
}

Child component :

<tr class="dossier-correspondencerow" *ngFor="let entry of attachmentEntries; let i = index" (click)="click()">

@Output() onClick = new EventEmitter();

click() {
    // do something
    this.onClick.emit()
}

↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓

Parent component(html)

<app-dossier-correspondence-list [correspondenceEntries]="correspondenceEntries" (onClick)="gotoItem($event)"> </app-dossier-correspondence-list>

Parent component(ts)

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {

  gotoItem(e) {
    console.log(e)
  }

}

Child component

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

@Component({
  selector: 'app-dossier-correspondence-list',
  template: `
    <table>
      <tr *ngFor="let entry of attachmentEntries; let i = index" (click)="click(i, entry.type)">
        {{entry.type}}
      </tr>
    </table>
  `
})
export class AppDossierCorrespondenceComponent  {

  @Input() correspondenceEntries: any;
  @Output() onClick = new EventEmitter();

  attachmentEntries = [
    { type: 'type1' },
    { type: 'type2' },
    { type: 'type3' },
  ]

  click(i, type) {
    this.onClick.emit({
      i: i,
      type: type
    })
  }

}

Link: https://stackblitz.com/edit/angular-ev6e5n

like image 67
Jonas Woo Avatar answered Sep 07 '25 20:09

Jonas Woo