Created
June 18, 2018 07:34
-
-
Save Theasker/c47d2d9aa5b9f5a1878c73c3f5da0a0e to your computer and use it in GitHub Desktop.
Number Input Component with thousands separator.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <scen-input-numerico [(value)]="numero" required ></scen-input-numerico> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { Component, OnInit, OnDestroy, Input, Output, SimpleChanges, EventEmitter, forwardRef, ElementRef, ViewChild, OnChanges } from '@angular/core'; | |
| import { ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms'; | |
| const NumDecimals: number = 2; | |
| @Component({ | |
| selector: 'scen-input-numerico', | |
| template: ` | |
| <input | |
| style="text-align:right;" | |
| class="form-control" | |
| type="text" | |
| #inputText | |
| [(ngModel)]="valueInputText" | |
| (focus)="onFocus($event);" | |
| (change)="onChange($event)" | |
| (blur)="onBlur($event)" | |
| (click)="onClick($event)" | |
| (mouseup)="$event.preventDefault()" | |
| (ngModelChange)="onChangeModel($event)" | |
| (keydown)="onKeydown($event)" | |
| (paste)="onPaste($event)" | |
| [disabled]="isDisabled" > | |
| `, | |
| providers: [ | |
| { | |
| provide: NG_VALUE_ACCESSOR, | |
| useExisting: forwardRef(() => ScenInputNumericoComponent), | |
| multi: true | |
| }, | |
| ] | |
| }) | |
| export class ScenInputNumericoComponent implements OnInit, OnDestroy, OnChanges, ControlValueAccessor { | |
| @Input('value') value: number; | |
| @Output() valueChange: EventEmitter<number> = new EventEmitter<number>(); | |
| @ViewChild('inputText') inputText: ElementRef; | |
| public valueInputText: string; | |
| private propagateChange = (_: any) => { }; | |
| private propagateTouch = (_: any) => { }; | |
| public isDisabled: boolean = false; | |
| private regexNumber: RegExp = new RegExp(/\d$/g); | |
| private copyPasteKeys: Array<string> = ['Control','Shift','c','x','v','Insert']; | |
| private copyPastePreviousKey: string; | |
| private InitialcopyPastePreviousKey: any = false; | |
| private specialKeys: Array<string> = ['Enter','Backspace','Tab','End','Home','ArrowRight','ArrowLeft','Delete',',']; | |
| private firstClick: boolean = false; | |
| constructor() { } | |
| ngOnInit(): void { | |
| // if (this.valueInputText == null || this.valueInputText == undefined) { | |
| // console.log('Inicializado'); | |
| // this.valueInputText = '0,00'; | |
| // this.value = 0; | |
| // } | |
| this.copyPastePreviousKey = ''; | |
| this.InitialcopyPastePreviousKey = setInterval(() => { | |
| this.copyPastePreviousKey = ''; | |
| }, 500); | |
| } | |
| ngOnDestroy(): void { | |
| if (this.InitialcopyPastePreviousKey) { | |
| clearInterval(this.InitialcopyPastePreviousKey); | |
| } | |
| } | |
| onFocus(event: any): void { | |
| if (this.valueInputText == null){ | |
| this.valueInputText = '0,00'; | |
| //this.valueInputText = ''; | |
| event.target.select(); | |
| } | |
| // Elimino todos los puntos ('.') del string | |
| let regex = /\./g; | |
| this.valueInputText = this.valueInputText.replace(regex, ''); | |
| event.target.select(); | |
| } | |
| onKeydown(event: KeyboardEvent): void { | |
| if (this.specialKeys.indexOf(event.key) != -1 || String(event.key).match(this.regexNumber) || event.key == ',') { | |
| if (event.key == ',') { | |
| if(this.valueInputText.search(',') >= 0) { | |
| event.preventDefault(); | |
| } | |
| } | |
| if (event.key == 'Enter') { | |
| //console.log('event.key: ', event.key); | |
| this.inputText.nativeElement.blur(); | |
| } | |
| return; | |
| } else if (this.copyPasteKeys.indexOf(event.key) != -1) { // Control de Copy & Paste | |
| if (event.key == 'Control' || event.key == 'Shift') { | |
| this.copyPastePreviousKey = event.key; | |
| } | |
| if (this.copyPasteKeys.indexOf(event.key) != -1 && (this.copyPastePreviousKey == 'Control' || this.copyPastePreviousKey == 'Shift')) { | |
| return; | |
| }else { | |
| event.preventDefault(); | |
| } | |
| } else { | |
| event.preventDefault(); | |
| } | |
| } | |
| onBlur(event: ClipboardEvent): void { | |
| let regex = /\./g; | |
| this.valueInputText = this.valueInputText.replace(regex, ''); | |
| this.valueInputText = this.thousandsSeparator(this.valueInputText); | |
| this.value = this.parseStringNumber(this.valueInputText); | |
| this.valueChange.emit(this.value); | |
| } | |
| onChange(event : any): void { | |
| // console.log('onChange'); | |
| // this.propagateChange(this.valueInputText); | |
| // this.valueInputText = this.thousandsSeparator(this.valueInputText); | |
| // this.value = this.parseStringNumber(this.valueInputText); | |
| // this.valueChange.emit(this.value); | |
| } | |
| ngOnChanges(changes: SimpleChanges): void { | |
| //console.log('changes.value.currentValue: ', changes.value.currentValue, ' / ', typeof(changes.value.currentValue)); | |
| // if (this.valueInputText == null ){ | |
| // this.valueChange.emit(0); | |
| // }else { | |
| // this.valueChange.emit(this.value); | |
| // } | |
| if (isNaN(changes.value.currentValue)) { | |
| this.valueInputText = this.thousandsSeparator(changes.value.currentValue); | |
| }else { | |
| this.valueInputText = this.thousandsSeparator(changes.value.currentValue.toString()); | |
| } | |
| this.value = this.parseStringNumber(this.valueInputText); | |
| this.valueChange.emit(this.value); | |
| this.valueChange.emit(changes.value.currentValue); | |
| } | |
| onClick(event: any): void { | |
| //console.log('this.firstClick: ', this.firstClick); | |
| if (!this.firstClick) { | |
| event.target.select(); | |
| this.firstClick = true; | |
| } | |
| //console.log('this.firstClick: ', this.firstClick); | |
| } | |
| onPaste(event: any): void { | |
| //console.log('onPaste'); | |
| let result: string = ''; | |
| let numComma = this.counterString(',',this.valueInputText); | |
| let patternNumber: any = /\d/; | |
| let patternChar: any = /\D/; | |
| let dirtyStringArray:string [] = event.target.value.split(''); | |
| for (let cont = 0; cont <= dirtyStringArray.length; cont++){ | |
| if (patternNumber.test(dirtyStringArray[cont])){ | |
| result = result + dirtyStringArray[cont]; | |
| }else if (patternChar.test(dirtyStringArray[cont])){ | |
| if (dirtyStringArray[cont] == ',' && numComma == 0){ | |
| result = result + ','; | |
| } | |
| } | |
| } | |
| this.valueInputText = result; | |
| } | |
| writeValue(value: any): void { | |
| // console.log('writeValue value: ', value); | |
| if (value) { | |
| this.valueInputText = value; | |
| } | |
| } | |
| registerOnChange(fn: (_: any) => void): void { | |
| this.propagateChange = fn; | |
| } | |
| registerOnTouched(fn: () => void): void { | |
| this.propagateTouch = fn; | |
| } | |
| onChangeModel(value: any) { | |
| console.log('onChangeModel value: ', value); | |
| } | |
| onTouch(event : any){ | |
| //console.log('onTouch'); | |
| this.propagateTouch(event); | |
| } | |
| setDisabledState(isDisabled: boolean): void { | |
| this.isDisabled = isDisabled; | |
| } | |
| private counterString (stringToSearch: string, search: string): number{ | |
| let i: number = 0; | |
| let counter: number = 0; | |
| while (i != -1) { | |
| i = stringToSearch.indexOf(search,i); | |
| if (i != -1) { | |
| i++; | |
| counter++; | |
| } | |
| } | |
| return counter; | |
| } | |
| private thousandsSeparator (stringNumber: string): string { | |
| let resultado: string; | |
| stringNumber = stringNumber.replace(',','.'); | |
| let flotante: number = parseFloat(stringNumber); | |
| let flotanteString = flotante.toFixed(2); | |
| resultado = flotanteString.replace('.', ','); | |
| let pos = resultado.indexOf(","); | |
| // string.substr(<desde>, <longitud>); | |
| while (pos > 3) { | |
| resultado = resultado.substr(0, pos-3)+'.'+resultado.substr(pos-3, 3)+resultado.substr(pos); | |
| pos=pos-3; | |
| } | |
| if (resultado == 'NaN') { | |
| return '0,00'; | |
| }else { | |
| return resultado; | |
| } | |
| } | |
| private parseStringNumber (stringNumber: string): number { | |
| let resultado: string; | |
| resultado = stringNumber; | |
| resultado = resultado.replace(/\./g, ''); | |
| resultado = resultado.replace(',', '.'); | |
| return parseFloat(resultado); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment