Skip to content

Force a pipe to be recomputed from within its code #60726

@mgirolet-gl

Description

@mgirolet-gl

Which @angular/* package(s) are relevant/related to the feature request?

core

Description

As per suggested by #15041 in 2017, it would be convenient to be allowed to trigger pipes manually for computation.

#15041 was however closed:

Looking into this (and similar) issues it sounds like we are looking for using a pipe as something akin to computed properties. We do consider a more generic solution. Since we are getting multiple issues / feature requests around computed properties, we've opened a canonical issue #47553 to track this use-case.

#47553 has since been closed too:

We do have computed properties with signals now!

Yet, I don't see any way signals can be used to solve #15041, which has since been locked for inactivity.

Here's a practical use case, as an example:

@Pipe({
    name: 'sortByTranslation'
})
export class SortByTranslationPipe implements PipeTransform, OnDestroy {
    private translateSub: any = null;

    constructor(private readonly translateService: TranslateService) { }

    ngOnDestroy(): void {
        if (this.translateSub !== null) this.translateSub.unsubscribe();
    }

    transform(input: string[]): any {
        input.sort((a: string, b: string) => {
            // Yes, this is heavily unoptimized, we recalculate translations on every comparison, you might want to use a dictionnary or something.
            // It doesn't matter, though: point is, you get data from an external source, and that data might change at any time.
            const aV = this.translateService.instant(a);
            const bV = this.translateService.instant(b);

            if (aV < bV)
                return -1;
            else if (aV > bV)
                return 1;
            else
                return 0;
        });

        if (this.translateSub === null) {
            this.translateSub = this.translateService.onLangChange.subscribe((value) => {
                /* TODO: manually trigger the pipe to be refreshed here!!! */
            });
        }
    }
}

In this case, we want to sort an array of translation keys alphabetically, depending on their actual translation value provided by some resource (here, a translation service).

However, if we change of language, we'd want to recompute the result of this pipe's transform function, which we can't do as of right now:

  • ChangeDetectorRef.markForCheck() and ChangeDetectorRef.detectChanges() do not detect any change and therefore won't refresh the pipe
  • There's no function in the PipeTransform interface that'd allow a forced recomputation

I'm using translations as an example here, but this could be applied to any callback-based data received from an external service of any kind.

Proposed solution

Either add a function / event emitter to pipes to refresh it, or add a public function to its ChangeDetectorRef to force it to be marked as changed, even if it doesn't detect changes by itself.

Alternatives considered

This could supposedly be solved by adding pure: false, but this would NOT be a good alternative: it would result in maaaaany unnecessary computations (or even "too many recursion" errors in some cases)

We don't want to recalculate data on the slightest change of anything, only when some callback we got control of is executed.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions