Angular - 将函数作为输入

And*_*y88 2 javascript typescript angular

我有一个动态创建的 modalComponent。

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

  <div class="modal-footer">
    <button (click)="callbackFunction()">success</button>
    <button>abort</button>
 </div>
</div>
Run Code Online (Sandbox Code Playgroud)

该组件有一个输入回调函数,我想从父组件调用该函数。

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() {}
}
Run Code Online (Sandbox Code Playgroud)

之后我创建了一个服务:

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
  ) {}
}
Run Code Online (Sandbox Code Playgroud)

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

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

sayHello(
 this.myService.doSomething();
}
Run Code Online (Sandbox Code Playgroud)

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

open(this.sayHello());
Run Code Online (Sandbox Code Playgroud)

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

我不想使用发射。

这是我的 stackblitz:示例

Ara*_*acy 6

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

ViewChild解决方案

  • 当按钮在父级上定义并且您想从子级获取某些内容时,可以使用此按钮。
///////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;
  }
}
Run Code Online (Sandbox Code Playgroud)

输出+EventEmitter解决方案

  • 在这种情况下,子级本身向父级发送一些内容(也就是按钮位于子级内部)
  • stackblic 上的实现
//////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()">
Run Code Online (Sandbox Code Playgroud)

主题

  • 使用 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
  }
}
Run Code Online (Sandbox Code Playgroud)