Home > Net >  Async in Custom pipe Angular
Async in Custom pipe Angular

Time:10-16

I'm currently working on an angular custom translation pipe which need a lot of async. Here is my current code

@Pipe({
  name: 'translatorPipe'
})
export class TranslatorPipe implements PipeTransform {

  constructor(private languageService: LanguageService) {}

  transform(input: string, ...args: unknown[]): Observable<Observable<string>> {
    let languageObservable = this.languageService.selectedLanguageObservable.pipe(map((response) => {
      let translationObservable = this.languageService.translateContent([input], response).pipe(map((translations) => {
        return this.languageService.getBestTranslationText(translations[0]);
      }));
      return translationObservable;
    }));
    return languageObservable;
  }
}

Problem is : to use this pipe, i have to combien it with a double async pip like follows :

{{ post.title | translatorPipe | async | async }}

Which is not really a good practice and a very anderstandable code.

My question is : How can i make my pipe self sufficient so i don't have to combine it with the async pipe.

Thanks by advance for your ideas

CodePudding user response:

That's indeed a bit too convoluted to me understandable. Perhaps it's best to just extend the async pipe and restructure your observable logic:

@Pipe({
  name: 'translator',
  pure: false,
})
export class TranslatorPipe extends AsyncPipe implements PipeTransform {
  private input$ = new ReplaySubject<string>(1);
  
  private language$ = this.ls.selectedLanguageObservable.pipe(
    switchMap((selectedLanguage) => this.input$.pipe(
      distinctUntilChanged(),
      switchMap((input) => this.ls.translateContent([input], selectedLanguage))
    )),
    map(([translations]) => this.ls.getBestTranslationText(translations)),
    shareReplay({ refCount: true, bufferSize: 1 })
  );
  
  constructor(private ls: LanguageService, cd: ChangeDetectorRef) {
    super(cd);
  }

  transform<T>(obj: Observable<T> | Subscribable<T> | Promise<T> | string): T | null;
  transform<T>(input: string): T | null {
    this.input$.next(input);
    
    return super.transform(this.language$);
  }
}

Usage:

{{ post.title | translator }}
  • Related