javascript - Angular 11: anropa funktion komponent i html med generisk pipe
Jag vill göra ett generiskt rör för att kalla en komponents funktion i komponentens HTML.
Fel sättet är t.ex.:
{{ test('foo') }}
min idé är:
{{ 'foo' | fn:test }}
detta är rörkoden
import { ChangeDetectorRef, EmbeddedViewRef, Type } from "@angular/core";
import { Pipe } from "@angular/core";
import { PipeTransform } from "@angular/core";
@Pipe({
name: "fn",
pure: true
})
export class FnPipe implements PipeTransform {
private context: any;
constructor(cdRef: ChangeDetectorRef) {
// retrive component instance (this is a workaround)
this.context = (cdRef as EmbeddedViewRef<Type<any>>).context;
}
public transform(
headArgument: any,
fnReference: Function,
...tailArguments: any[]
): any {
return fnReference.apply(this.context, [headArgument, ...tailArguments]);
}
}
och detta är ett komponentexempel
import { Component } from "@angular/core";
@Component({
selector: "my-app",
template: `
<!-- testFromPipe har a third parameter name for trigger pipe refresh -->
PIPE: {{ "arg1" | fn: testFromPipe:"arg2":name }}<br /><br />
<!-- wrong way for call a function nto html just for test the result -->
HTML: {{ testFromHtml("arg1", "arg2") }}<br /><br />
<button (click)="triggerCD()">test</button>
`
})
export class AppComponent {
name = null;
constructor() {
this.triggerCD();
}
test(a: string, b: string) {
// test multiple arguments anch this scope works
return `a:${a}; b:${b}; name:${this.name};`;
}
testFromHtml(a: string, b: string) {
console.log("FUNCTION");
return this.test(a, b);
}
testFromPipe(a: string, b: string) {
console.log("PIPE");
return this.test(a, b);
}
triggerCD() {
this.name = new Date().getMinutes();
}
}
detta är ett liveexempel https://stackblitz.com/edit/angular-ivy-jvmcgz
koden verkar fungera men är baserad på att hämta komponentinstansen till pipen via den privata egenskapskontexten i ChangeDetectorRef.
constructor(cdRef: ChangeDetectorRef) {
this.context = (cdRef as EmbeddedViewRef<Type<any>>).context;
}
Detta är osäkert och framtida uppdateringar av Angular kan bryta detta trick.
Finns det ett säkert sätt att få tillgång till en komponentinstans i en Pipe?