Как связать родительский дочерний компонент с событием click - PullRequest
1 голос
/ 26 сентября 2019

У меня есть приложение Angular 8.И у меня есть родительские и дочерние отношения.

Итак, у меня есть функция в родительском DossierCorrespondenceComponent, но функция должна быть запущена в дочернем компоненте.

Итак, у меня есть эта функция в родительском:

@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;
  }

И я пытаюсь вызвать ее в дочернем компоненте DossierCorrespondenceListComponent так:

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

Но ничего не происходит

Так что я должен изменить?

Но у меня есть другой компонент DossierCorrespondenceAttachmentsComponent, который также использует эту функцию:

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

Так что, если мне нужно переместить функцию gotoItem(index, type: string) для обоих дочерних компонентов, чем у меня есть дубликат кода.

Теперь у меня это так в родительском компоненте:

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

и родительский компонент ts:

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;
  }

и дочерний компонент:

  <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>



и дочерний компонент ts:


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();
  }


}

Но затем я получаю эту ошибку:

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)

, и я изменил это:

 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 

Ответы [ 3 ]

1 голос
/ 26 сентября 2019

Родительский компонент :

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

gotoItem() {
    //do something
}

Дочерний компонент :

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

@Output() onClick = new EventEmitter();

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

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

Родительский компонент (html)

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

Родителькомпонент (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)
  }

}

дочерний компонент

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
    })
  }

}

Ссылка: https://stackblitz.com/edit/angular-ev6e5n

1 голос
/ 26 сентября 2019

DossierCorrespondenceComponent.html :

<app-child (callYourFunction)="yourFunction()"</app-child>

DossierCorrespondenceComponent.ts :

yourFunction() {
}

child.component.ts

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

@Output() callYourFunction = new EventEmitter();

На событие, которое вы хотите вызвать родительский компонент:

this.callYourFunction.emit(true)
0 голосов
/ 26 сентября 2019

Родительский компонент:

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

@Component({
 selector: 'my-app',
 template: `
  <hello [name]="name" (callParentFunc)="parentFunc()"></hello>
  <p [class.red]="clicked">
   This is text from parent component
  </p>
 `,
 styles: [`
  p {
   font-family: Lato;
  }

  p.red {
   color: red;
  }
`]
})
export class AppComponent  {
 name = 'Click me';
 clicked: boolean;

 parentFunc() {
  this.clicked = !this.clicked;
 }
}

Дочерний компонент:

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

@Component({
 selector: 'hello',
 template: `<h1>
 Child component <a (click)="childClick()">{{name}}</a>
  </h1>`,
 styles: [`h1 { font-family: Lato; }`]
})
export class HelloComponent  {
 @Input() name: string;
 @Output() callParentFunc: EventEmitter<any> = new EventEmitter<any>();

 childClick() {
  this.callParentFunc.emit();
 }
}

Я создал стек для вас, это может помочь:

https://stackblitz.com/edit/angular-c9egd6

...