0

I'm developing an Angular 2 SPA. My application is composed by:

  • One component
  • One directive

I've builded one directive that format text input using onfocus and onblur events. On focus event remove dots to text value, on blur event add thousand dots to text value.

Following component's code:

<div>
    <input id="input" [(ngModel)]="numero" InputNumber />
</div>

Following component's TypeScript code:

import { Component } from '@angular/core';

@Component({
    selector: 'counter',
    templateUrl: './counter.component.html'
})
export class CounterComponent {
    numero: number;

    public incrementCounter() {
    }

    ngOnInit() {
        this.numero = 100100100;
    }
}

Following directive's TypeScript code:

import { Directive, HostListener, ElementRef, OnInit } from "@angular/core";

@Directive({ selector: "[InputNumber]" })
export class InputNumber implements OnInit, OnChanges {

    private el: HTMLInputElement;

    constructor(private elementRef: ElementRef) {
        this.el = this.elementRef.nativeElement;
    }

    ngOnInit(): void {
       // this.el.value is empty
       console.log("Init " + this.el.value);
       this.el.value = this.numberWithCommas(this.el.value);
    }

    ngOnChanges(changes: any): void {
       // OnChanging value this code is not executed...
       console.log("Change " + this.el.value);
       this.el.value = this.numberWithCommas(this.el.value);
    }

    @HostListener("focus", ["$event.target.value"])
    onFocus(value: string) {
        this.el.value = this.replaceAll(value, ".", "");
    }

    @HostListener("blur", ["$event.target.value"])
    onBlur(value: string) {
        this.el.value = this.numberWithCommas(value);
    }

    private numberWithCommas(x) {
        return x.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
    }

    private escapeRegExp(str) {
        return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
    }

    private replaceAll(str, find, replace) {
        return str.replace(new RegExp(this.escapeRegExp(find), 'g'), replace);
    }
}

The following code works except that I need lost focus for show my number like "100.100.100". How can I perform this action on init data loading?

I add one example at this link: Plnkr example

Thanks

ilMattion
  • 1,841
  • 2
  • 24
  • 47

2 Answers2

0

I think that your directive should implement ControlValueAccessor interface https://angular.io/docs/ts/latest/api/forms/index/ControlValueAccessor-interface.html It is needed for writing model in your directive. ControlValueAccessor interface has writeValue(value: any) method that will be initially called. So your writeValue method will be something like this:

private onChange: (_: any) => {};
...
writeValue(val) {
   const editedValue = this.numberWithCommas(val);
   this._onChange(val);
}


registerOnChange(fn: any) : void {
  this._onChange = fn;
}
longroad
  • 405
  • 4
  • 13
  • Hi proJS. I've tried to use the ControlValueAccessor but I neved used this angular's element. Please, if you can, can I have one example? I've added one Plnkr on question. Thanks – ilMattion May 12 '17 at 13:38
0

You can do this by using a Pipe which takes a boolean parameter that represents your focus/no focus action.

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'dots'})
export class DotsPipe implements PipeTransform {
  transform(value: number, hasFocus:boolean): any {
    if(hasFocus){
      return value.toString().replace(/\./g,'');
    }else{
      return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
    }
  }
}

Then you have to apply the Pipe on your [ngModel] and use Angular events (focus) and (focusout) to change your variable.

<input [ngModel]="numero | dots : hasFocus" (focus)="hasFocus=true" (focusout)="hasFocus=false" (ngModelChange)="numero=$event" />
Gianluca Paris
  • 1,391
  • 1
  • 14
  • 25