How to re-trigger all pure pipes on all component tree in Angular 2

前端 未结 6 2222
青春惊慌失措
青春惊慌失措 2021-02-12 09:29

I have pure pipe TranslatePipe that translates phrases using LocaleService that has locale$: Observable current locale. I al

6条回答
  •  挽巷
    挽巷 (楼主)
    2021-02-12 10:13

    You can also create your own unpure pipe to track external changes. Check the sources of native Async Pipe to get the main idea.

    All you need is to call ChangeDetectorRef.markForCheck(); inside of your unpure pipe every time your Observable return new locale string. My solution:

    @Pipe({
      name: 'translate',
      pure: false
    })
    export class TranslatePipe implements OnDestroy, PipeTransform {
    
      private subscription: Subscription;
      private lastInput: string;
      private lastOutput: string;
    
      constructor(private readonly globalizationService: GlobalizationService,
                  private readonly changeDetectorRef: ChangeDetectorRef) {
        this.subscription = this.globalizationService.currentLocale // <- Observable of your current locale
          .subscribe(() => {
            this.lastOutput = this.globalizationService.translateSync(this.lastInput); // sync translate function, will return string
            this.changeDetectorRef.markForCheck();
          });
      }
    
      ngOnDestroy(): void {
        if (this.subscription) {
          this.subscription.unsubscribe();
        }
        this.subscription = void 0;
        this.lastInput = void 0;
        this.lastOutput = void 0;
      }
    
      transform(id: string): string { // this function will be called VERY VERY often for unpure pipe. Be careful.
        if (this.lastInput !== id) {
          this.lastOutput = this.globalizationService.translateSync(id);
        }
        this.lastInput = id;
        return this.lastOutput;
      }
    }
    

    Or you even can incapsulate AsyncPipe inside your pipe (not a good solution, just for example):

    @Pipe({
      name: 'translate',
      pure: false
    })
    export class TranslatePipe implements OnDestroy, PipeTransform {
    
      private asyncPipe: AsyncPipe;
      private observable: Observable;
      private lastValue: string;
    
      constructor(private readonly globalizationService: GlobalizationService,
                  private readonly changeDetectorRef: ChangeDetectorRef) {
        this.asyncPipe = new AsyncPipe(changeDetectorRef);
      }
    
      ngOnDestroy(): void {
        this.asyncPipe.ngOnDestroy();
        this.lastValue = void 0;
        if (this.observable) {
          this.observable.unsubscribe();
        }
        this.observable = void 0;
        this.asyncPipe = void 0;
      }
    
      transform(id: string): string {
        if (this.lastValue !== id || !this.observable) {
          this.observable = this.globalizationService.translateObservable(id); // this function returns Observable
        }
        this.lastValue = id;
    
        return this.asyncPipe.transform(this.observable);
      }
    
    }
    

提交回复
热议问题