angularlocalizationangular-pipeangular-date-format

Dynamically change of date and number pipe default format


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


Solution

  • 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