AngularJS有&参数,你可以把一个回调传递给一个指令(例如AngularJS的回调方式)。是否可以将回调函数作为@Input传递给Angular组件(如下所示)?如果不是,那最接近AngularJS的功能是什么?

@Component({
    selector: 'suggestion-menu',
    providers: [SuggestService],
    template: `
    <div (mousedown)="suggestionWasClicked(suggestion)">
    </div>`,
    changeDetection: ChangeDetectionStrategy.Default
})
export class SuggestionMenuComponent {
    @Input() callback: Function;

    suggestionWasClicked(clickedEntry: SomeModel): void {
        this.callback(clickedEntry, this.query);
    }
}


<suggestion-menu callback="insertSuggestion">
</suggestion-menu>

当前回答

更新

这个答案是在Angular 2还处于alpha阶段的时候提交的,当时很多特性都无法使用/没有文档记录。虽然下面的方法仍然有效,但这种方法现在已经完全过时了。我强烈推荐下面接受的答案。

原来的答案

是的,事实上它是,但是你要确保它的作用域是正确的。为此,我使用了一个属性来确保这意味着我想要的。

@Component({
  ...
  template: '<child [myCallback]="theBoundCallback"></child>',
  directives: [ChildComponent]
})
export class ParentComponent{
  public theBoundCallback: Function;

  public ngOnInit(){
    this.theBoundCallback = this.theCallback.bind(this);
  }

  public theCallback(){
    ...
  }
}

@Component({...})
export class ChildComponent{
  //This will be bound to the ParentComponent.theCallback
  @Input()
  public myCallback: Function; 
  ...
}

其他回答

例如,我使用了一个登录模态窗口,其中模态窗口是父窗口,登录表单是子窗口,登录按钮调用了父窗口的关闭函数。

父模态包含关闭模态的函数。这个父组件将close函数传递给登录子组件。

import { Component} from '@angular/core';
import { LoginFormComponent } from './login-form.component'

@Component({
  selector: 'my-modal',
  template: `<modal #modal>
      <login-form (onClose)="onClose($event)" ></login-form>
    </modal>`
})
export class ParentModalComponent {
  modal: {...};

  onClose() {
    this.modal.close();
  }
}

在子登录组件提交登录表单后,它使用父模块的回调函数关闭父模块

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

@Component({
  selector: 'login-form',
  template: `<form (ngSubmit)="onSubmit()" #loginForm="ngForm">
      <button type="submit">Submit</button>
    </form>`
})
export class ChildLoginComponent {
  @Output() onClose = new EventEmitter();
  submitted = false;

  onSubmit() {
    this.onClose.emit();
    this.submitted = true;
  }
}

以下是我在Angular 13中的工作(截至2022年3月)。

附注:这与其他人的回答或多或少有些相似。添加这个答案只是为了让人们知道它可以在Angular 13中工作。

在父组件中将函数定义为平箭头函数,而不是常规函数。

callBackFn= (args: string): void => {
  // callback code here
  // This will work (Flat Arrow)
}
// callbackFn(args: string): void {
//   //This type of definition will not work.
// }

将回调函数作为属性传递给子组件

<app-child [callBack]=”callBackFn”></app-child>

在子组件中接收回调函数作为Input。该定义应该与父类中定义的定义相匹配。

@Input() callBack: (args: string) => void;

然后在子组件中调用该函数。你也可以称它为子组件模板。

this.callBack('Test');

OR

<button (click)="callBack('Test')"></button>

但不确定这种方法是否好。 我在ReactJS中看到了类似的方法,它工作得很好,但仍然不确定它在angular中是如何工作的,以及它的影响是什么。

请对这一办法提出任何意见。

对于我来说,除了.bind(this)之外,我还必须在要执行的方法名称后面加上一对括号。

在父组件中:

在.ts文件中:

    this.pillTabs = [
        { tabName: 'Subscribers', tabMethod: this.showSubscribers.bind(this) },
        { tabName: 'Exemplars', tabMethod: this.showExemplars.bind(this) }
    ];

在.html文件中:

    <pill-tabs [pillTabs]="pillTabs"></pill-tabs>

在Child组件中:

在.ts文件中:

    @Input() pillTabs: PillTab[];

在.html文件中:

    <div *ngFor="let pillTab of pillTabs; let i = index">
        <input type="radio" id="{{'radio-' + i}}" name="tabs" [checked]="pillTab.checked"
            (click)="pillTab.tabMethod()" />
        <label class="tab" for="{{'radio-' + i}}">{{pillTab.tabName}}</label>
    </div>

当我没有对括号后面的方法时,代码是不工作的:

      (click)="pillTab.tabMethod"

然后当我在这里加上一对括号,代码就开始工作了。

      (click)="pillTab.tabMethod()"

我希望有人觉得它有帮助。

我认为这是一个糟糕的解决方案。如果你想通过@Input()将Function传递给组件,@Output()装饰器就是你要找的。

export class SuggestionMenuComponent {
    @Output() onSuggest: EventEmitter<any> = new EventEmitter();

    suggestionWasClicked(clickedEntry: SomeModel): void {
        this.onSuggest.emit([clickedEntry, this.query]);
    }
}

<suggestion-menu (onSuggest)="insertSuggestion($event[0],$event[1])">
</suggestion-menu>

SnareChops给出的另一个答案。

你可以在模板中使用.bind(this)来达到同样的效果。它可能没有那么干净,但它节省了几行。我现在使用的是angular 2.4.0

@Component({
  ...
  template: '<child [myCallback]="theCallback.bind(this)"></child>',
  directives: [ChildComponent]
})
export class ParentComponent {

  public theCallback(){
    ...
  }
}

@Component({...})
export class ChildComponent{
  //This will be bound to the ParentComponent.theCallback
  @Input()
  public myCallback: Function; 
  ...
}