Angular 2 pipe with variable parameter

10,739

Solution 1

Pipe:

 @Pipe(name: 'tempConverter')
 export class TemperatureConverterPipe implements PipeTransform {

      // Selected temperature unit
      //private unit: string;

      constructor(){

      }

      // Return temperature
      transform(value: number,unit:string): number {
        switch(unit){
          case "c":
            return value;
            break;
          case "f":
            return celsiusToFahrenheit(value);
            break;
          default:
           return value;
        }
      }

      // Convert celsius temp to fahrenheit
      celsiusToFahrenheit(value: number){
         return value * 9/5 + 32;
      }

    }

HTML call:

[temperatureProperty]="value | tempConverter:unit"

Subscribe to the service in the ngOninit of calling component and pass unit.

Solution 2

You can make the pipe impure

@Pipe(name: 'tempConvert', pure: false)
export class TemperatureConverterPipe ...

this way the pipe is called every time change detection is run. With impure pipes you should ensure that the pipe doesn't do any expensive work because it will be called very often.

Share:
10,739
Admin
Author by

Admin

Updated on June 23, 2022

Comments

  • Admin
    Admin almost 2 years

    I'm in the course of learning Angular2/Ionic2 so please excuse my ignorance. I got to learning Pipes and everything seemed easy until I stumbled on this problem. Let me demonstrate the problem using a perfect example with temperatures.

    Say that I have pipe which return Celisus or Fahrenheit temperature value, depending on the setting saved on localStorage (Celsius is default input value).

    So I created a Pipe which do this:

    export class TemperatureConverterPipe implements PipeTransform {
    
      // Selected temperature unit
      private unit: string;
    
      constructor(private settings: Settings){
        // Get immediately the temperature unit from localStorage
        // And subscribe to changes
        this.settings.radio().subscribe(data => {
          this.unit = data.temp_unit
        });
      }
    
      // Return temperature
      transform(value: number): number {
        switch(this.unit){
          case "c":
            return value;
            break;
          case "f":
            return celsiusToFahrenheit(value);
            break;
          default:
           return value;
        }
      }
    
      // Convert celsius temp to fahrenheit
      celsiusToFahrenheit(value: number){
         return value * 9/5 + 32;
      }
    
    }
    

    Problems I'm stuck at:

    1. How this pipe can watch for parameter change (Temperature unit) and return the new values (e.q. C to F)? Because currently it only watches for Input (Temperature value) changes.
    2. Is this a correct way to solve this?

    Thank you very much!

  • Poul Kruijt
    Poul Kruijt over 7 years
    Darn, I'm facing a 'problem' as well, where I do not want to use an impure pipe, but still want to be able to force a refresh on a pipe, because a client setting has changed. Now this is still a non expensive pipe, but I can imagine that there will be situations where it will be. Do you know if they are going to implement something in the near future? A force refresh on a certain pipe :) (i know this doesn't belong here in the comments, but hey, we are wearing cool hats)
  • Günter Zöchbauer
    Günter Zöchbauer over 7 years
    An alternative way is to pass a parameter that changes, like [prop]="value | myPipe:dummyCounter". Whenever dummyCounter` changes, the pipe will be called. I wouldn't expect changes to be made to the pipe implementation in the near future.
  • Admin
    Admin over 7 years
    I forgot to mention a tried creating an impure pipe, the problem is I think this is not the best solution. Can't I just manually invoke recalculating values on unit change?
  • Günter Zöchbauer
    Günter Zöchbauer over 7 years
    No, the only ways are the value or parameters changing (for pure pipes) or change detection being run (for impure pipes). You can use ChangeDetectionStrategy.OnPush and detach the change detector in your component to limit the number of times change detection is run to limit performance impact when using impure pipes (this is a good idea anyway no matter if you use impure pipes or not).
  • Admin
    Admin over 7 years
    Your way worked perfectly fine, but I can't belive how complex it is to solve such a simple task. Anyway thank you Suraj, you just made my day much better.