Skip to content

Instantly share code, notes, and snippets.

@Theasker
Created June 18, 2018 07:34
Show Gist options
  • Select an option

  • Save Theasker/c47d2d9aa5b9f5a1878c73c3f5da0a0e to your computer and use it in GitHub Desktop.

Select an option

Save Theasker/c47d2d9aa5b9f5a1878c73c3f5da0a0e to your computer and use it in GitHub Desktop.
Number Input Component with thousands separator.
<scen-input-numerico [(value)]="numero" required ></scen-input-numerico>
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