【问题标题】:Angular - Pass function as inputAngular - 传递函数作为输入
【发布时间】:2021-04-19 13:24:48
【问题描述】:

我有一个动态创建的 modalComponent。

<div class="modal">
  <div class="modal-body">
    Test
  </div>

  <div class="modal-footer">
    <button (click)="callbackFunction()">success</button>
    <button>abort</button>
 </div>
</div>

这个组件有一个 Input callbackFunction,这是一个我想从我的父组件调用的函数。

import {
  Component,
  Input,
  OnInit,
  QueryList,
  ViewChildren
} from "@angular/core";
import { ModalService } from "../modal.service";

@Component({
  selector: "app-modal",
  templateUrl: "./modal.component.html",
  styleUrls: ["./modal.component.css"]
})
export class ModalComponent implements OnInit {
  @Input() callbackFunction: () => void;

  constructor(private modalService: ModalService) {}

  ngOnInit() {}
}

之后我创建了一个服务:

import {
  ApplicationRef,
  ComponentFactoryResolver,
  ComponentRef,
  Injectable,
  Injector
} from "@angular/core";

import { ModalComponent } from "./modal/modal.component";

@Injectable()
export class ModalService {
  dialogComponentRef: ComponentRef<ModalComponent>;

  open(callbackFunction: any) {
   const modalComponentFactory = this.cfResolver.resolveComponentFactory(ModalComponent);

   const modalComponent = modalComponentFactory.create(this.injector);

   modalComponent.instance.callbackFunction = callbackFunction;

   this.dialogComponentRef = modalComponent;

   document.body.appendChild(modalComponent.location.nativeElement);

   this.appRef.attachView(modalComponent.hostView);
  }

  close() {
    this.appRef.detachView(this.dialogComponentRef.hostView);
  }

  constructor(
    private appRef: ApplicationRef,
    private cfResolver: ComponentFactoryResolver,
    private injector: Injector
  ) {}
}

在 componentFactoryResolver 之后,我将函数作为实例传递。

在我的父控制器中,我创建了一个函数

sayHello(
 this.myService.doSomething();
}

然后我创建一个用于打开模式的函数

open(this.sayHello());

当我单击按钮并调用回调函数时,“this”不是指父组件而是指模态组件,并且 sayHello 是未定义的。我该如何解决这种情况?

我不想使用 emit。

这是我的堆栈闪电战:Example

【问题讨论】:

标签: javascript angular typescript


【解决方案1】:

对此基本上有三种解决方案:Output + EventEmitter@ViewChildSubject

ViewChild 解决方案

  • 当按钮在 Parent 上定义并且您想从 Child 获取某些东西时,可以使用此按钮。
///////parent.component.ts
...
import { ChildComponent } from 'child/child.component';
...
export class ParentComponent {
  @ViewChild(ChildComponent) childComponent: ChildComponent;

  public buttonClick(): void {
    let childResponse = this.childComponent.getValues();//will return '1234'
    ...
  }
}
///////child.component.ts
export class ChildComponent {
  valueInsideChild = '1234';

  public getValues(): string {
    return this.valueInsideChild;
  }
}

输出 + EventEmitter 解决方案

//////parent.component.html
<child-selector
  ($buttonClicked)=clickAction($event)>
</child-selector>
//////parent.component.ts
...
export class ParentComponent {
  public clickAction(value: string): void {
    console.log(value);//will log 'something1234 when child button is clicked
  }
}
//////child.component.ts
...
import { Output, Component, EventEmitter } from '@angular/core';
...
export class ChildComponent {
  @Output() $buttonClicked = new EventEmitter<string>();

  public click(): void {
    this.$buttonClicked.emit('something1234');
  }
}
//////child.component.html
<button (click)="click()">

主题

  • 使用您的 modalService+subject+observables 接口响应
///app.component.ts
...
export class AppComponent {
...
  open() {
    //subscribe to the observable :)
    this.modalService.open(this.sayHello).subscribe(response => {
      alert(response.text);
    });
  }
...
}
///modal.component.html
...
  <button (click)="click()">success</button>
...
///modal.component.ts
...
export class ModalComponent {
  constructor(private modalService: ModalService) {}
  ...
  public click(): void {
    this.modalService.close({text: 'Hello World'});
  }
}
///modal.service.ts
...
import { Subject, Observable } from 'rxjs';
...
export class ModalService {
...
  private _modalResponse = new Subject<any>();
...
  open(): Observable<any> {//this is your open function
    ...
    return this._modalResponse.asObservable();//return an observable where the modal responses will be emitted
  }
  
  close(response: any): void {
    //receives a value from the modal component when closing
    this.appRef.detachView(this.dialogComponenRef.hostView);
    this._modalResponse.next(response);//emit the response on the Observable return when open was called
  }
}

【讨论】:

    【解决方案2】:

    我建议您使用OutputEventEmitter 从子组件调用父组件函数,Angular 文档提供了一个很好的示例。

    https://angular.io/guide/inputs-outputs#sending-data-to-a-parent-component

    【讨论】:

      猜你喜欢
      • 2023-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-23
      • 2014-01-22
      • 2018-12-16
      • 1970-01-01
      • 2022-06-14
      相关资源
      最近更新 更多