-1

I'm implementing an Angular application, where I let the user choose the localization parameters (language, date format, number format, etc.) and after the selection the interface gets updated instantly, without having to recompile or relaunch the application. I already implemented this for the language by using the 'ngx-translate' library.

Is there any way to have the same for dates and numbers format?

An interesting idea is to override the date and the number pipes. But how could I have these pipes default to a value which is chosen at runtime by the user?

I'm using Angular 14.

Thanks,

Thomas

zeroquaranta
  • 392
  • 4
  • 16
  • I think just providing the date format as a variable would work. Whenever the value of format variable is updated, Angular will update the template. {{ dateToFormat | date: dateFormat }} So, you can keep the format in a service maybe and when that is updated, it will propagate to all components. – Awais Saeed Aug 29 '23 at 11:21

2 Answers2

0

You can extend date and the number pipes, make them impure and track changes to localization params inside.

You can not override built-in pipes, you will have to use different names.

kemsky
  • 14,727
  • 3
  • 32
  • 51
  • Ok, no problem with using a different name. The idea is to have exactly the same behaviour of the system date pipe, except using the format specified at runtime and provided by a service, rather than using the DATE_PIPE_DEFAULT_OPTIONS – zeroquaranta Aug 30 '23 at 07:32
0

So far the best and cleanest solution I have found is the one taken from here:

https://github.com/ngx-translate/core/issues/897#issuecomment-574692576

which I've extended with a service that holds the current format chosen by the user (in a more realistic context, the chosen option would be saved/retrieved through API call)

date-format.service.ts

@Injectable({
    providedIn: 'root'
})
export class DateFormatService {

    private format?: string = undefined;

    constructor() {} 

    public useFormat(format: string) {
        this.format = format;
    }

    public currentFormat(): any{
        return this.format;
    }
}

custom-date.pipe.ts

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

    constructor(
        private translateService: TranslateService, // provided by ngx-translate
        private dateFormatService: DateFormatService
    ) {}

    transform(date: any): any {
        const datePipe: DatePipe = new DatePipe(this.translateService.currentLang);
        return datePipe.transform(date, this.dateFormatService.currentFormat());     
    } 
}

number-format.service.ts

@Injectable({
    providedIn: 'root'
})
export class NumberFormatService {

    private format?: string = undefined;

    constructor() {} 

    public useFormat(format: string) {
        this.format = format;
    }

    public currentFormat(): any{
        return this.format;
    }
}

custom-number.pipe.ts

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

  constructor(
    private numberFormatService: NumberFormatService,
    private translateService: TranslateService // provided by ngx-translate
  ){}

  transform(number: any): any {
    const numberPipe = new DecimalPipe(this.translateService.currentLang);
    return numberPipe.transform(number, this.numberFormatService.currentFormat());
  }

}

The pipes use the system pipe to localize the value depending on the current language selected through ngx-translate. Then optionally use the same system pipe instance to the format provided by the service (and selected by the user)

This solution appear to work perfectly, date and decimal number formats are updated instantly after the user selection.

I was wondering if there is any hidden side effect, like memory leak due to too many event triggered, or unsubscribed observers, etc.

Anybody aware of any problem this solution could bring?

Thanks,

Thomas

zeroquaranta
  • 392
  • 4
  • 16