angularangular2-directives

Custom directive to convert percent


I am trying to create a custom directive in Angular 2 which will change the value of an input ngModel to percent for example

number / 100

example image

This is an example image of what I am trying to achieve.

For example, the user sees the 5.12, but the value which will be sent to the backend should be 5.12 / 100, and the user shouldn't see this.

I have come to an approach, but, I think, that is a wrong approach, can you guys help me out?

This is my code.

For example, when it comes from backend to be multiplied by 100, and when it goes to backend to be divided by 100.


Solution

  • import { Directive, ElementRef, Input, forwardRef, EventEmitter } from '@angular/core';
    import { ControlValueAccessor, NG_VALUE_ACCESSOR, NgModel } from "@angular/forms";
    
    @Directive({
        selector: '[ngModel][toPercentage]',
        providers: [{
            provide: NG_VALUE_ACCESSOR,
            useExisting: forwardRef(() => ToPercentDirective),
            multi: true
        }],
        host: {
            "[value]": 'ngModel',
            '(blur)': 'onBlur()'
        }
    })
    export class ToPercentDirective implements ControlValueAccessor {
    
        constructor(private el: ElementRef) { }
    
        private innerValue: string;
        private toNumber: number;
        private toPercent: number;
    
        public onChangeCallback: any = (_) => { console.log(_) }
        public onTouched: any = () => { /*Empty*/ }
    
        onBlur() {
            var input = this.el.nativeElement.value;
            this.toPercent = parseFloat(input) / 100;
    
            if (input != this.toNumber) {
                this.onChangeCallback(this.toPercent);
            }
        }
    
        get value(): any {
            console.log(this.innerValue);
            return this.innerValue;
        };
    
        //set accessor including call the onchange callback
        set value(v: any) {
            if (v !== this.innerValue) {
                this.innerValue = v;
                this.onChangeCallback(v);
            }
        }
    
        writeValue(val: string): void {
            // this.ngModel.ControlValueAccessor.writeValue(val);
            this.toNumber = parseFloat(val) * 100;
            this.el.nativeElement.value = this.toNumber;
        }
    
        registerOnChange(fn: any): void {
            // console.log(fn);
            this.onChangeCallback = fn;
        }
    
        registerOnTouched(fn: any): void {
            // console.log(fn);
            this.onTouched = fn;
        }
    }
    

    I am posting this answer for anyone facing a similar issue.

    it handles this problem: converts a number * 100 when it comes from backend and converts a number / 100 when it sends to backend.

    but the user doesn't see these operations.

    for example:

    response  = 0.5
    
    toNumber = 0.5 * 100 -> <input number> 50 
    toPercent= 50 / 100 -> <input number> 50, value = 0.5
    

    hope it helps anyone