Suppose I have my own pipe which looks like this (dummy example)
@Pipe({ name: 'myPipe' })
export class MyPipe implements PipeTransform {
private lastKey: string;
constructor(private myService: MyService) {
myService.onSomeVariableChange.subscribe((r) => {
console.log('now i should be transformed again');
});
}
transform(value: any, ...args: any[]) {
return `${value} ${this.myService.someVariable}`;
}
}
HTML
<span> {{ 'SomeText' | myPipe }} </span>
I simply return the input with a suffix which is variable. The pipe knows the variable has been changed through the event onSomeVariableChange
. The Angular framework should now call transform
again.
But since my pipe is pure (and I really don't want it to be impure) and since my input does not change (only an external variable), the transform is not automatically called.
How can I, from within my pipe, force this method to be called? Note that this is a DUMMY EXAMPLE. The real scenario is a lot more complex, so the ideal solution would not be to circumvent this non-existing scenario. The ideal solution would be a way to force transform
to be called again.
CodePudding user response:
If the pipe is impure
it will update on every change detection cycle - but you could try triggering change detection yourself only when the data updates e.g
constructor(private myService: MyService, cd: ChangeDetectorRef) {
myService.onSomeVariableChange.subscribe((r) => {
console.log('now i should be transformed again');
cd.detectChanges();
});
}
I haven't tested this, so not fully sure if it will run the pipe transform again - you may also need to add in cd.markForCheck()
CodePudding user response:
I wouldn't use pipe here, instead, i would use a custom directive like this:
import { Directive, ElementRef, Input } from '@angular/core';
@Directive({
selector: '[appMyMagicDir]'
})
export class MyMagicDirDirective {
@Input() appMyMagicDir: string;
constructor(private elementRef: ElementRef, private myService: MyService) {
myService.onSomeVariableChange.subscribe(res => {
elementRef.nativeElement.innerHTML = `${appMyMagicDir}${res}`
} )
}
}
then on your element just apply the directive like this:
<span [appMyMagicDir]="someTextVar"></span>
or alternatively and probably simpler -
<span>{{SomeTextVar}}{{myService.onSomeVariableChange | async}}</span>