Berk Akkerman
Berk Akkerman

Reputation: 483

Promise in Pipe transform

I don't want to use "| async pipe" because I don't want to get data for every component. My transform function below:

 transform(key: string, ...args) {
  this.storage.get("dictionary").then((dict) => {         
   var translated = dict[key] || "noResource";
   console.log("key = "+key + ", value = "+translated);
   return translated; 
  });  
}

I can get key and values but value does not rendered. I tried ngZone but not working.

Upvotes: 6

Views: 12117

Answers (2)

martin
martin

Reputation: 96889

If you want the pipe to be asynchronous and update itself later I think the only way is by using WrappedValue.

For example like this where the Promise updates the pipe after 1s. In your use-case it's going the work exactly the same way.

See live demo: https://stackblitz.com/edit/angular-knamur?file=src%2Fapp%2Ftest-async.ts

@Pipe({name: 'testAsync', pure: false})
export class TestAsyncPipe implements PipeTransform {

  private val: number;
  private originalValue: number;

  constructor(private _ref: ChangeDetectorRef) {}

  transform(value: number): any {
    if (value === this.originalValue) {
      return this.val;
    } else {
      new Promise(resolve => {
        setTimeout(() => resolve(value * 2), 1000) ;
      }).then((v: number) => {
        this.val = v + 1;
        this._ref.markForCheck();
      });
    }

    this.originalValue = value;
    this.val = value;

    return WrappedValue.wrap(value);
  }
}

Then in template use:

{{ 42 | testAsync }}

After 1s it'll update the template and show 85.

Upvotes: 3

Pierre Mallet
Pierre Mallet

Reputation: 7221

I don't understand why you don't want to use the only "buildin" pipe that matches your case.

says your pipe is :

 @Pipe({name: 'mypipe'})
    export class MyPipe implements PipeTransform
    {
        transform(key: string, ...args) {
            // watch out you missed the return statement !!
            -->return<-- this.storage.get("dictionary").then((dict) => {         
            var translated = dict[key] || "noResource";
            console.log("key = "+key + ", value = "+translated);
            return translated; 
        });  
    }

the in your template you could just use

{{ 'mykey' | mypipe | async }}

If you don't want to use async pipe you will be forced to mimic is logic who is already dead simple and bug proof. No gain for you.

Upvotes: 9

Related Questions