Wie übergebe ich in einer Angular 2+ -Komponente eine Callback-Funktion, die Parameter übernimmt?
<app-example [onComplete]="doThing('someParam')"></app-example>
Und manchmal brauche ich keine Parameter wie diese:
<app-example [onComplete]="doSomeThingElse()"></app-example>
Und dann in der Komponente, die ich habe
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class ExampleComponent {
@Input() public onComplete: () => void;
//run `this.onComplete()` somewhere as needed
}
Was jedoch am Ende passiert, ist, dass die doThing('someParam')
oder doSomeThingElse()
sofort ohne Interaktion aufgerufen wird.
Wie soll ich Callback-Funktionen an eine Komponente übergeben, die später aufgerufen werden soll?
Das eigentliche Problem, das ich hier zu lösen versuche, ist, dass Sie alle übergebenen Funktionen zu einem späteren Zeitpunkt ausführen können. Dies ist für eine Bestätigungskomponente, in der der Benutzer gefragt wird "Sind Sie sicher, dass Sie fortfahren möchten?" Wenn dann die Schaltfläche "Ja, ich bin sicher" gedrückt wird, wird die übergebene Funktion ausgeführt.
Hier ist ein Beispiel für die @Output
-Syntax, die @toskv gesucht hat: Angular übergibt die Callback-Funktion als @Input.
Also für dein Beispiel
<app-example
(onComplete)="doThing()"
[completedParam]="'someParam'"></app-example>
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class ExampleComponent {
@Output() public onComplete: EventEmitter<any> = new EventEmitter();
@Input() completedParam;
runOnComplete(): void {
this.onComplete.emit(this.completedParam);
}
}
Fühlt sich nicht so gut wie [onComplete]="doThing.bind(this, 'someParam')"
.
Vorlage:
<app-example [someParams]="someParamsObject"
(complete)="onComplete($event)" >
</app-example>
Komponente:
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class ExampleComponent {
@Input()
someParams: YourParamsType;
@Output()
complete:EventEmitter<any> = new EventEmitter<any>();
//run `this.complete(this.someParams)` somewhere as needed and
//pack in some params if you need
}
In Ihrer aufrufenden übergeordneten Komponente benötigen Sie eine Funktion mit dem Namen onComplete
, die in diesem Fall Parameter des Typs any
erhält (die aus @Output
stammt, die als EventEmitter<any>
definiert ist). Bei Bedarf können Sie auch Ereignisparameter eines beliebigen Typs verwenden, der EventEmitter<YourParticularType>
gefällt.
Sie können eine private Methode in Ihrer Komponente haben:
private doThingFactory(param) {
return () => this.doThing(param);
}
und benutze es dann so:
<app-example [onComplete]="doThingFactory('someParam')"></app-example>
Diese Lösung funktioniert nur, wenn Sie über eine Methode verfügen, die aufgerufen werden muss, ohne die Komponente selbst zu aktivieren. In meinem Fall muss ich jedoch eine beobachtbare Methode in der App-Beispielkomponente ausführen und warten, bis die Antwort eine Aktion innerhalb dieser Komponente ausführt.
Wenn jemand das gleiche Problem hat. Hier ist die Lösung dafür.
erstellen Sie eine Schnittstelle.
export interface Delegate<T> {
(...args: any[]): T;
}
Erstellen Sie in Ihrer Winkelkomponente eine @Input
-Variable
@Component({
selector: 'app-example',
templateUrl: './example.component.html',
})
export class AppExampleComponent {
@Input() executeWhen: Delegate<Observable<any>>;
runOnComplete(): void {
this.executeWhen().subscribe(() => // do some action);
}
}