src/components/sq-input-number-form-control/sq-input-number-form-control.component.ts
Componente de input numérico que estende SqInputMaskFormControlComponent. Configura automaticamente a máscara para valores numéricos inteiros com separador de milhares.
O valor exibido segue o FormControl reativo: null, undefined ou string vazia permanecem vazios
(não há preenchimento automático com zero). Quem precisar de 0 inicial deve definir no formulário.
```html
<sq-input-number-form-control
[formControl]="quantityControl"
[label]="'Quantidade'"
></sq-input-number-form-control><sq-input-number-form-control [formControl]="ageControl" [label]="'Idade'" [minValue]="0" [maxValue]="120"
Example :
SqInputMaskFormControlComponent
OnInit
| changeDetection | ChangeDetectionStrategy.OnPush |
| providers |
{
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SqInputNumberFormControlComponent), multi: true,
}
|
| selector | sq-input-number-form-control |
| standalone | true |
| imports |
NgClass
NgStyle
NgTemplateOutlet
ReactiveFormsModule
NgxMaskDirective
SqTooltipComponent
UniversalSafePipe
|
| styleUrls | ./sq-input-number-form-control.component.scss |
| templateUrl | ../sq-input-mask-form-control/sq-input-mask-form-control.component.html |
Properties |
|
Methods |
|
Inputs |
|
Outputs |
HostListeners |
| emptyWhenZero | |
Type : boolean
|
|
Default value : true
|
|
|
Quando true (padrão), o valor numérico zero (0, "0", "0,00" etc.) é tratado como vazio: não preenche o input
e o CVA emite |
|
| incrementValue | |
Type : number
|
|
Default value : 1
|
|
|
Valor de incremento/decremento ao pressionar Arrow Up/Down. |
|
| allowNegativeNumbers | |
Type : boolean
|
|
Default value : false
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:119
|
|
|
Indicates whether negative numbers are allowed. |
|
| decimalMarker | |
Type : "." | "," |
|
|
Default value : ['.', ',']
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:125
|
|
|
The decimal marker character or an array of characters to represent decimal values. |
|
| leadZero | |
Type : boolean
|
|
Default value : false
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:138
|
|
|
Indicates whether leading zeros should be preserved. |
|
| mask | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:83
|
|
|
The mask pattern for input validation and formatting. Example : |
|
| maxValue | |
Type : number
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:150
|
|
|
Defines the maximum value that can be accepted as input (for numeric masks). |
|
| minValue | |
Type : number
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:144
|
|
|
Defines the minimum value that can be accepted as input (for numeric masks). |
|
| patterns | |
Type : | undefined
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:74
|
|
|
Custom regex patterns for mask tokens (ngx-mask |
|
| placeHolderCharacter | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:132
|
|
|
The character to use as a placeholder in empty mask slots. Example : |
|
| prefix | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:107
|
|
|
The prefix to be prepended to the input value. Example : |
|
| showMaskTyped | |
Type : boolean
|
|
Default value : false
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:113
|
|
|
Indicates whether the mask should be visible while typing. |
|
| suffix | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:99
|
|
|
The suffix to be appended to the input value. Example : |
|
| thousandSeparator | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
|
Defined in
SqInputMaskFormControlComponent:91
|
|
|
The character used as a thousand separator in numeric input. Example : |
|
| inputMode | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqInputFormControlComponent
|
|
|
Defined in
SqInputFormControlComponent:69
|
|
|
Input mode for mobile devices. |
|
| timeToChange | |
Type : number
|
|
Default value : 0
|
|
|
Inherited from
SqInputFormControlComponent
|
|
|
Defined in
SqInputFormControlComponent:59
|
|
|
Time in milliseconds for debouncing value changes. When set to a value > 0, the value change will be debounced. |
|
| type | |
Type : "text" | "email" | "email-multiple" | "hidden" | "password" | "tel" | "url" | "file"
|
|
Default value : 'text'
|
|
|
Inherited from
SqInputFormControlComponent
|
|
|
Defined in
SqInputFormControlComponent:64
|
|
|
Type of the input element (e.g., text, email, password). |
|
| customClass | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:55
|
|
|
Custom CSS class for the input element. |
|
| id | |
Type : string
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:45
|
|
|
The id attribute for the input element. |
|
| label | |
Type : string
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:50
|
|
|
An optional label for the input. |
|
| name | |
Type : string
|
|
Default value : `random-name-${(1 + Date.now() + Math.random()).toString().replace('.', '')}`
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:40
|
|
|
The name attribute for the input element. |
|
| placeholder | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:60
|
|
|
Placeholder text for the input element. |
|
| readonly | |
Type : boolean
|
|
Default value : false
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:65
|
|
|
Flag to make the input element readonly. |
|
| tooltipColor | |
Type : string
|
|
Default value : 'inherit'
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:80
|
|
|
Color of the tooltip. |
|
| tooltipIcon | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:85
|
|
|
Icon for the tooltip. |
|
| tooltipMessage | |
Type : string
|
|
Default value : ''
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:70
|
|
|
Tooltip message to display. |
|
| tooltipPlacement | |
Type : "center top" | "center bottom" | "left center" | "right center"
|
|
Default value : 'right center'
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:75
|
|
|
Placement of the tooltip. |
|
| blurred | |
Type : EventEmitter<FocusEvent>
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:100
|
|
|
Event emitter for blur events. |
|
| focused | |
Type : EventEmitter<FocusEvent>
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:95
|
|
|
Event emitter for focus events. |
|
| valueChange | |
Type : EventEmitter<any>
|
|
|
Inherited from
SqFormControlBaseDirective
|
|
|
Defined in
SqFormControlBaseDirective:90
|
|
|
Event emitter for input value changes. |
|
| Private decrementNumber |
decrementNumber()
|
|
Decrementa o valor pelo incrementValue.
Returns :
void
|
| Private getNumericValue |
getNumericValue()
|
|
Obtém o valor numérico atual do controle.
Returns :
number
|
| Private incrementNumber |
incrementNumber()
|
|
Incrementa o valor pelo incrementValue.
Returns :
void
|
| Private isZeroLike | ||||||||
isZeroLike(value: any)
|
||||||||
|
Indica se o valor deve ser tratado como zero “semântico” (ex.: 0, "0", "0,00") quando
Parameters :
Returns :
boolean
|
| ngOnInit |
ngOnInit()
|
|
Inherited from
SqFormControlBaseDirective
|
|
Defined in
SqFormControlBaseDirective:72
|
|
Configura os valores padrão para input numérico.
Returns :
void
|
| onKeyDown | ||||||||
onKeyDown(event: KeyboardEvent)
|
||||||||
Decorators :
@HostListener('keydown', ['$event'])
|
||||||||
|
Trata eventos de teclado para incrementar ou decrementar o valor (setas ↑ / ↓).
Parameters :
Returns :
void
|
| writeValue | ||||||||
writeValue(value: any)
|
||||||||
|
Inherited from
SqFormControlBaseDirective
|
||||||||
|
Defined in
SqFormControlBaseDirective:93
|
||||||||
|
ControlValueAccessor: sincroniza o valor do FormControl pai com o controle interno.
Com
Parameters :
Returns :
void
|
| watchValueChanges |
watchValueChanges()
|
|
Inherited from
SqFormControlBaseDirective
|
|
Defined in
SqFormControlBaseDirective:97
|
|
Override the watchValueChanges method to add debounce time.
Returns :
void
|
| ngOnDestroy |
ngOnDestroy()
|
|
Inherited from
SqFormControlBaseDirective
|
|
Defined in
SqFormControlBaseDirective:136
|
|
Cleanup on component destruction.
Returns :
void
|
| onBlur | ||||||||
onBlur(event: FocusEvent)
|
||||||||
|
Inherited from
SqFormControlBaseDirective
|
||||||||
|
Defined in
SqFormControlBaseDirective:198
|
||||||||
|
Handle blur events. Marks the control as touched when the user leaves the input.
Parameters :
Returns :
void
|
| onFocus | ||||||||
onFocus(event: FocusEvent)
|
||||||||
|
Inherited from
SqFormControlBaseDirective
|
||||||||
|
Defined in
SqFormControlBaseDirective:208
|
||||||||
|
Handle focus events. Emits the focused event when the input receives focus.
Parameters :
Returns :
void
|
| registerOnChange | ||||||||
registerOnChange(fn: any)
|
||||||||
|
Inherited from
SqFormControlBaseDirective
|
||||||||
|
Defined in
SqFormControlBaseDirective:153
|
||||||||
|
ControlValueAccessor: Registers a callback function that is called when the control's value changes.
Parameters :
Returns :
void
|
| registerOnTouched | ||||||||
registerOnTouched(fn: any)
|
||||||||
|
Inherited from
SqFormControlBaseDirective
|
||||||||
|
Defined in
SqFormControlBaseDirective:161
|
||||||||
|
ControlValueAccessor: Registers a callback function that is called when the control is touched.
Parameters :
Returns :
void
|
| setDisabledState | ||||||||
setDisabledState(isDisabled: boolean)
|
||||||||
|
Inherited from
SqFormControlBaseDirective
|
||||||||
|
Defined in
SqFormControlBaseDirective:169
|
||||||||
|
ControlValueAccessor: Sets the disabled state of the control.
Parameters :
Returns :
void
|
| resolvedMaskPatterns |
Default value : initialConfig.patterns
|
|
Inherited from
SqInputMaskFormControlComponent
|
|
Defined in
SqInputMaskFormControlComponent:70
|
|
Resolved ngx-mask token patterns used by the directive after applying the |
| labelTemplate |
Type : TemplateRef<HTMLElement> | null
|
Default value : null
|
Decorators :
@ContentChild('labelTemplate')
|
|
Inherited from
SqInputFormControlComponent
|
|
Defined in
SqInputFormControlComponent:87
|
|
Reference to a label template. |
| leftLabel |
Type : TemplateRef<HTMLElement> | null
|
Default value : null
|
Decorators :
@ContentChild('leftLabel')
|
|
Inherited from
SqInputFormControlComponent
|
|
Defined in
SqInputFormControlComponent:75
|
|
Reference to a left-aligned label template. |
| nativeElement |
Type : ElementRef
|
Default value : inject(ElementRef)
|
|
Inherited from
SqInputFormControlComponent
|
|
Defined in
SqInputFormControlComponent:92
|
|
Reference to the native element. |
| rightLabel |
Type : TemplateRef<HTMLElement> | null
|
Default value : null
|
Decorators :
@ContentChild('rightLabel')
|
|
Inherited from
SqInputFormControlComponent
|
|
Defined in
SqInputFormControlComponent:81
|
|
Reference to a right-aligned label template. |
| control |
Default value : new FormControl<any>(null)
|
|
Inherited from
SqFormControlBaseDirective
|
|
Defined in
SqFormControlBaseDirective:105
|
|
Internal FormControl for managing the input value and state. |
| Protected destroy$ |
Default value : new Subject<void>()
|
|
Inherited from
SqFormControlBaseDirective
|
|
Defined in
SqFormControlBaseDirective:110
|
|
Subject for managing subscriptions. |
| Protected onChange |
Type : function
|
Default value : () => {...}
|
|
Inherited from
SqFormControlBaseDirective
|
|
Defined in
SqFormControlBaseDirective:117
|
|
ControlValueAccessor callback function called when the value changes. Registered via registerOnChange(). |
| Protected onTouched |
Type : function
|
Default value : () => {...}
|
|
Inherited from
SqFormControlBaseDirective
|
|
Defined in
SqFormControlBaseDirective:124
|
|
ControlValueAccessor callback function called when the control is touched. Registered via registerOnTouched(). |
import { Component, Input, forwardRef, OnInit, ChangeDetectionStrategy, HostListener } from '@angular/core';
import { NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
import { NgClass, NgStyle, NgTemplateOutlet } from '@angular/common';
import { NgxMaskDirective } from 'ngx-mask';
import { SqInputMaskFormControlComponent } from '../sq-input-mask-form-control/sq-input-mask-form-control.component';
import { SqTooltipComponent } from '../sq-tooltip/sq-tooltip.component';
import { UniversalSafePipe } from '../../pipes/universal-safe/universal-safe.pipe';
/**
* Componente de input numérico que estende SqInputMaskFormControlComponent.
* Configura automaticamente a máscara para valores numéricos inteiros com separador de milhares.
*
* O valor exibido segue o FormControl reativo: `null`, `undefined` ou string vazia permanecem vazios
* (não há preenchimento automático com zero). Quem precisar de `0` inicial deve definir no formulário.
*
* @example
* ```html
* <sq-input-number-form-control
* [formControl]="quantityControl"
* [label]="'Quantidade'"
* ></sq-input-number-form-control>
*
* <!-- Com limites -->
* <sq-input-number-form-control
* [formControl]="ageControl"
* [label]="'Idade'"
* [minValue]="0"
* [maxValue]="120"
* ></sq-input-number-form-control>
* ```
*/
@Component({
selector: 'sq-input-number-form-control',
templateUrl: '../sq-input-mask-form-control/sq-input-mask-form-control.component.html',
styleUrls: ['./sq-input-number-form-control.component.scss'],
standalone: true,
imports: [
NgClass,
NgStyle,
NgTemplateOutlet,
ReactiveFormsModule,
NgxMaskDirective,
SqTooltipComponent,
UniversalSafePipe,
],
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => SqInputNumberFormControlComponent),
multi: true,
},
],
})
export class SqInputNumberFormControlComponent extends SqInputMaskFormControlComponent implements OnInit {
/**
* Valor de incremento/decremento ao pressionar Arrow Up/Down.
* @default 1
*/
@Input() incrementValue = 1;
/**
* Quando true (padrão), o valor numérico zero (0, "0", "0,00" etc.) é tratado como vazio: não preenche o input
* e o CVA emite `null` para o FormControl pai (necessário com máscara `separator` + ngx-mask, que senão exibe "0").
* Use `[emptyWhenZero]="false"` quando o zero for um valor válido a mostrar e enviar.
*/
@Input() emptyWhenZero = true;
/**
* Configura os valores padrão para input numérico.
*/
override ngOnInit(): void {
// Máscara para números inteiros com separador de milhares
this.mask = 'separator';
// Formato brasileiro como padrão
if (this.thousandSeparator === '') {
this.thousandSeparator = '.';
}
// Input mode numérico para dispositivos móveis
this.inputMode = 'numeric';
super.ngOnInit();
}
/**
* ControlValueAccessor: sincroniza o valor do FormControl pai com o controle interno.
* Com `emptyWhenZero`, evita que ngx-mask exiba "0" quando o modelo traz zero — normaliza para vazio e emite `null`.
*
* @param value - Valor enviado pelo Angular Forms (número, string mascarada ou null).
*/
override writeValue(value: any): void {
if (!this.emptyWhenZero) {
super.writeValue(value);
return;
}
if (this.isZeroLike(value)) {
super.writeValue(null);
queueMicrotask(() => this.onChange(null));
return;
}
super.writeValue(value);
}
/**
* Trata eventos de teclado para incrementar ou decrementar o valor (setas ↑ / ↓).
*
* @param event - Evento `keydown` do input.
*/
@HostListener('keydown', ['$event'])
onKeyDown(event: KeyboardEvent): void {
if (event.key === 'ArrowUp') {
event.preventDefault();
this.incrementNumber();
} else if (event.key === 'ArrowDown') {
event.preventDefault();
this.decrementNumber();
}
}
/**
* Incrementa o valor pelo incrementValue.
*/
private incrementNumber(): void {
const currentValue = this.getNumericValue();
const newValue = currentValue + this.incrementValue;
this.control.setValue(String(newValue));
}
/**
* Decrementa o valor pelo incrementValue.
*/
private decrementNumber(): void {
const currentValue = this.getNumericValue();
const newValue = currentValue - this.incrementValue;
// Não permite negativos se allowNegativeNumbers for false
if (!this.allowNegativeNumbers && newValue < 0) {
this.control.setValue(this.emptyWhenZero ? null : '0');
return;
}
if (this.emptyWhenZero && newValue === 0) {
this.control.setValue(null);
return;
}
this.control.setValue(String(newValue));
}
/**
* Obtém o valor numérico atual do controle.
*/
private getNumericValue(): number {
const value = this.control.value;
if (value === null || value === undefined || value === '') {
return 0;
}
// Remove separadores de milhar para parsear
const normalized = String(value).replace(/\./g, '');
return parseInt(normalized, 10) || 0;
}
/**
* Indica se o valor deve ser tratado como zero “semântico” (ex.: 0, "0", "0,00") quando `emptyWhenZero` está ativo.
*
* @param value - Valor bruto do modelo ou do input.
* @returns `true` se for equivalente a zero numérico; `false` para null, undefined, string vazia ou números ≠ 0.
*/
private isZeroLike(value: any): boolean {
if (value === null || value === undefined || value === '') {
return false;
}
if (value === 0) {
return true;
}
if (typeof value === 'string') {
const trimmed = value.trim();
if (trimmed === '') {
return false;
}
const normalized = trimmed.replace(/\./g, '').replace(/,/g, '.');
const n = Number(normalized);
return !Number.isNaN(n) && n === 0;
}
return false;
}
}
<div class="wrapper-all-inside-input {{ customClass }}">
@if (label?.length || tooltipMessage || labelTemplate) {
<label
class="display-flex"
[ngClass]="{
readonly: readonly,
}"
[for]="id"
>
@if (label && !labelTemplate) {
<div [innerHtml]="label | universalSafe"></div>
}
@if (labelTemplate) {
<div>
<ng-container *ngTemplateOutlet="labelTemplate"></ng-container>
</div>
}
@if (tooltipMessage) {
<sq-tooltip
class="ml-1"
[message]="tooltipMessage"
[placement]="tooltipPlacement"
[color]="tooltipColor"
[icon]="tooltipIcon"
></sq-tooltip>
}
</label>
}
<div
class="p-0 wrapper-input wrapper-input-squid text-ellipsisarea"
[ngClass]="{
readonly: readonly,
}"
>
@if (leftLabel) {
<span class="input-group-text m-0">
<ng-container *ngTemplateOutlet="leftLabel"></ng-container>
</span>
}
<input
class="col input"
[ngClass]="{
disabled: disabled,
readonly: readonly,
}"
[id]="id"
type="text"
[name]="name"
[placeholder]="placeholder || ''"
[readonly]="readonly"
[formControl]="control"
(blur)="onBlur($event)"
(focus)="onFocus($event)"
[attr.inputmode]="inputMode"
[patterns]="resolvedMaskPatterns"
mask="{{ mask }}"
[thousandSeparator]="thousandSeparator"
[suffix]="suffix"
[prefix]="prefix"
[showMaskTyped]="showMaskTyped"
[allowNegativeNumbers]="allowNegativeNumbers"
[decimalMarker]="decimalMarker"
[placeHolderCharacter]="placeHolderCharacter"
[leadZero]="leadZero"
/>
@if (rightLabel) {
<span class="input-group-text m-0">
<ng-container *ngTemplateOutlet="rightLabel"></ng-container>
</span>
}
</div>
</div>
./sq-input-number-form-control.component.scss
// Importa os estilos do componente pai (mask-form-control)
@use '../sq-input-mask-form-control/sq-input-mask-form-control.component';