File

src/ng-xform/number-field/input-number.component.ts

Description

Component to generate input field form numbers

Implements

ControlValueAccessor AfterViewInit

Metadata

providers { : , : , : true }
selector ng-xform-input-number
templateUrl ./input-number.component.html

Index

Properties
Methods
Inputs
Outputs
Accessors

Constructor

constructor(elementRef: ElementRef, renderer: Renderer2, locale: string)
Parameters :
Name Type Optional Description
elementRef ElementRef
renderer Renderer2
locale string

Inputs

formatOptions

Default value: { notation: 'auto' }

inputClass

Default value: ''

inputId

Default value: ''

inputStyle

Default value: ''

Outputs

keypress $event type: EventEmitter
paste $event type: EventEmitter

Methods

Private getFutureValue
getFutureValue(event: KeyboardEvent)
Parameters :
Name Type Optional Description
event KeyboardEvent
Returns : any
Private getValueAsNumber
getValueAsNumber()
Returns : number
ngAfterViewInit
ngAfterViewInit()
Returns : void
registerOnChange
registerOnChange(fn: any)
Parameters :
Name Type Optional Description
fn any
Returns : void
registerOnTouched
registerOnTouched(fn: any)
Parameters :
Name Type Optional Description
fn any
Returns : void
setDisabledState
setDisabledState(isDisabled: boolean)
Parameters :
Name Type Optional Description
isDisabled boolean
Returns : void
toLocaleString
toLocaleString(value: number)
Parameters :
Name Type Optional Description
value number
Returns : any
writeValue
writeValue(value: any)
Parameters :
Name Type Optional Description
value any
Returns : void

Properties

_onChange
_onChange:
Default value : (value: any) => { }
_onTouched
_onTouched:
Default value : () => { }
Readonly Private allowedKeys
allowedKeys:
Default value : ['+', '-', 'e', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
Private decimalSeparator
decimalSeparator: string
Type : string
Private input
input: HTMLInputElement
Type : HTMLInputElement
Private isValidNumber
isValidNumber: RegExp
Type : RegExp
Readonly Private specialKeys
specialKeys:
Default value : ['Enter', 'Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'Tab']
Private thousandSeparator
thousandSeparator: string
Type : string
viewModel
viewModel:
Default value : ''

Accessors

formattedValue
getformattedValue()
import { getLocaleNumberSymbol, NumberSymbol } from '@angular/common';
import {
  AfterViewInit,
  Component,
  ElementRef,
  EventEmitter,
  Inject,
  Input,
  LOCALE_ID,
  Output,
  Renderer2,
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import * as math from 'mathjs';


/**
 * Component to generate input field form numbers
 */
@Component({
  selector: 'ng-xform-input-number',
  templateUrl: './input-number.component.html',
  providers: [{
    provide: NG_VALUE_ACCESSOR,
    useExisting: InputNumberComponent,
    multi: true
  }],
})
export class InputNumberComponent implements ControlValueAccessor, AfterViewInit {

  @Output() paste = new EventEmitter();
  @Output() keypress = new EventEmitter<KeyboardEvent>();
  @Input() formatOptions = { notation: 'auto' };
  @Input() inputClass = '';
  @Input() inputStyle = '';
  @Input() inputId = '';
  viewModel = '';

  private input: HTMLInputElement;
  private isValidNumber: RegExp;
  private readonly allowedKeys = ['+', '-', 'e', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'];
  private readonly specialKeys = ['Enter', 'Backspace', 'Delete', 'ArrowLeft', 'ArrowRight', 'Home', 'End', 'Tab'];
  private thousandSeparator: string;
  private decimalSeparator: string;

  _onChange = (value: any) => { };
  _onTouched = () => { };

  constructor(private elementRef: ElementRef, private renderer: Renderer2, @Inject(LOCALE_ID) locale: string) {
    this.thousandSeparator = getLocaleNumberSymbol(locale, NumberSymbol.Group);
    this.decimalSeparator = getLocaleNumberSymbol(locale, NumberSymbol.Decimal);
    this.allowedKeys.push(this.decimalSeparator);
    this.isValidNumber = new RegExp(
      `^(([+\\-]?(?:(?:\\d{1,3}(?:\\${this.thousandSeparator}\\d{1,3})+)|\\d*))(?:\\${this.decimalSeparator}(\\d*))?)` +
      `(?:(?:[e]{0,1}([+\-]?\\d*)))?$`
    );
  }

  ngAfterViewInit() {
    this.input = this.elementRef.nativeElement.querySelector('input');
    this.input.oninput = () => {
      this._onChange(this.getValueAsNumber());
    };
    this.input.onkeypress = (event: KeyboardEvent) => {
      this.keypress.emit(event);
      if (event.ctrlKey || this.specialKeys.indexOf(event.key) >= 0) {
        return;
      }
      if (this.allowedKeys.indexOf(event.key) < 0 || !this.isValidNumber.test(this.getFutureValue(event))) {
        event.preventDefault();
      }
    }
    this.input.onpaste = (event: Event) => this.paste.emit(event);
  }

  private getFutureValue(event: KeyboardEvent) {
    const input: any = event['target'];
    return input.value.slice(0, input.selectionStart) +
      event.key +
      input.value.slice(input.selectionEnd, input.value.length);
  }

  public get formattedValue() {
    return this.viewModel != null ? this.viewModel : '-';
  }

  private getValueAsNumber(): number {
    if ((this.viewModel === '') || this.viewModel == null) {
      return null;
    } else if (!this.isValidNumber.test(this.viewModel)) {
      return NaN;
    }
    const value = this.viewModel.replace(this.thousandSeparator, '').replace(this.decimalSeparator, '.');
    return Number(value);
  }

  toLocaleString(value: number) {
    let formatedValue = math.format(value, this.formatOptions);
    if (this.decimalSeparator !== '.') {
      return formatedValue.replace('.', this.decimalSeparator);
    }
    return formatedValue;
  }

  writeValue(value: any): void {
    this.viewModel = value != null ? this.toLocaleString(Number(value)) : null;
  }

  registerOnChange(fn: any): void {
    this._onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this._onTouched = fn;
  }

  setDisabledState(isDisabled: boolean): void {
    if (!this.input) {
      return;
    }
    if (isDisabled) {
      this.renderer.setAttribute(this.input, 'disabled', undefined);
    } else {
      this.renderer.removeAttribute(this.input, 'disabled');
    }
  }

}
<input id="{{inputId}}" [(ngModel)]="viewModel" [ngModelOptions]="{standalone: true}" [ngClass]="inputClass" [ngStyle]="inputStyle" />
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""