src/number-input/number.component.ts
Get started with importing the module:
Example :import { NumberModule } from 'carbon-components-angular';
ControlValueAccessor
providers |
{
provide: NG_VALUE_ACCESSOR, useExisting: NumberComponent, multi: true
}
|
selector | cds-number, ibm-number |
template |
|
Properties |
|
Methods |
Inputs |
Outputs |
HostBindings |
HostListeners |
Accessors |
constructor(i18n: I18n)
|
||||||
Defined in src/number-input/number.component.ts:297
|
||||||
Creates an instance of
Parameters :
|
ariaLabel | |
Type : string
|
|
Defined in src/number-input/number.component.ts:247
|
|
Sets the arialabel for input |
decrementLabel | |
Type : string | Observable
|
|
Defined in src/number-input/number.component.ts:254
|
disabled | |
Type : boolean
|
|
Default value : false
|
|
Defined in src/number-input/number.component.ts:169
|
|
Set to |
fluid | |
Type : boolean
|
|
Default value : false
|
|
Defined in src/number-input/number.component.ts:274
|
|
Experimental: enable fluid state |
helperText | |
Type : string | TemplateRef<any>
|
|
Defined in src/number-input/number.component.ts:223
|
|
Sets the optional helper text. |
id | |
Type : string
|
|
Default value : `number-${NumberComponent.numberCount}`
|
|
Defined in src/number-input/number.component.ts:181
|
|
The unique id for the number component. |
incrementLabel | |
Type : string | Observable
|
|
Defined in src/number-input/number.component.ts:263
|
invalid | |
Type : boolean
|
|
Default value : false
|
|
Defined in src/number-input/number.component.ts:177
|
|
Set to |
invalidText | |
Type : string | TemplateRef<any>
|
|
Defined in src/number-input/number.component.ts:227
|
|
Sets the invalid text. |
label | |
Type : string | TemplateRef<any>
|
|
Defined in src/number-input/number.component.ts:219
|
|
Sets the text inside the |
max | |
Type : any
|
|
Default value : null
|
|
Defined in src/number-input/number.component.ts:215
|
|
Sets the max attribute on the |
min | |
Type : any
|
|
Default value : null
|
|
Defined in src/number-input/number.component.ts:211
|
|
Sets the min attribute on the |
placeholder | |
Type : string
|
|
Default value : ""
|
|
Defined in src/number-input/number.component.ts:185
|
|
Sets the placeholder attribute on the |
precision | |
Type : number
|
|
Defined in src/number-input/number.component.ts:235
|
|
If |
readonly | |
Type : boolean
|
|
Default value : false
|
|
Defined in src/number-input/number.component.ts:160
|
|
Set to |
required | |
Type : boolean
|
|
Defined in src/number-input/number.component.ts:193
|
|
Reflects the required attribute of the |
size | |
Type : "sm" | "md" | "lg"
|
|
Default value : "md"
|
|
Defined in src/number-input/number.component.ts:189
|
|
Number input field render size |
skeleton | |
Type : boolean
|
|
Default value : false
|
|
Defined in src/number-input/number.component.ts:173
|
|
Set to |
step | |
Type : number
|
|
Default value : 1
|
|
Defined in src/number-input/number.component.ts:231
|
|
Sets the amount the number controls increment and decrement by. |
theme | |
Type : "light" | "dark"
|
|
Default value : "dark"
|
|
Defined in src/number-input/number.component.ts:165
|
value | |
Type : any
|
|
Defined in src/number-input/number.component.ts:197
|
|
Sets the value attribute on the |
warn | |
Type : boolean
|
|
Default value : false
|
|
Defined in src/number-input/number.component.ts:239
|
|
Set to |
warnText | |
Type : string | TemplateRef<any>
|
|
Defined in src/number-input/number.component.ts:243
|
|
Sets the warning text |
change | |
Type : EventEmitter
|
|
Defined in src/number-input/number.component.ts:251
|
|
Emits event notifying other classes when a change in state occurs in the input. |
class.cds--form-item |
Type : boolean
|
Default value : true
|
Defined in src/number-input/number.component.ts:155
|
class.cds--number-input--fluid--disabled |
Type : boolean
|
Defined in src/number-input/number.component.ts:280
|
class.cds--number-input--fluid--focus |
Type : boolean
|
Defined in src/number-input/number.component.ts:284
|
class.cds--number-input--fluid--invalid |
Type : boolean
|
Defined in src/number-input/number.component.ts:276
|
class.cds--text-input--fluid__skeleton |
Type : boolean
|
Defined in src/number-input/number.component.ts:288
|
focusout |
focusout()
|
Defined in src/number-input/number.component.ts:330
|
emitChangeEvent |
emitChangeEvent()
|
Defined in src/number-input/number.component.ts:418
|
Creates a class of
Returns :
void
|
focusOut |
focusOut()
|
Decorators :
@HostListener('focusout')
|
Defined in src/number-input/number.component.ts:330
|
Returns :
void
|
getDecrementLabel |
getDecrementLabel()
|
Defined in src/number-input/number.component.ts:407
|
Returns :
Observable<string>
|
getIncrementLabel |
getIncrementLabel()
|
Defined in src/number-input/number.component.ts:411
|
Returns :
Observable<string>
|
handleFocus | ||||||
handleFocus(event: FocusEvent)
|
||||||
Defined in src/number-input/number.component.ts:435
|
||||||
Parameters :
Returns :
void
|
Public isTemplate | ||||
isTemplate(value)
|
||||
Defined in src/number-input/number.component.ts:431
|
||||
Parameters :
Returns :
boolean
|
onDecrement |
onDecrement()
|
Defined in src/number-input/number.component.ts:382
|
Subtracts
Returns :
void
|
onIncrement |
onIncrement()
|
Defined in src/number-input/number.component.ts:354
|
Adds
Returns :
void
|
onNumberInputChange | ||||
onNumberInputChange(event)
|
||||
Defined in src/number-input/number.component.ts:426
|
||||
Parameters :
Returns :
void
|
Public registerOnChange | ||||||
registerOnChange(fn: any)
|
||||||
Defined in src/number-input/number.component.ts:317
|
||||||
Sets a method in order to propagate changes back to the form.
Parameters :
Returns :
void
|
Public registerOnTouched | ||||||||
registerOnTouched(fn: any)
|
||||||||
Defined in src/number-input/number.component.ts:325
|
||||||||
Registers a callback to be triggered when the control has been touched.
Parameters :
Returns :
void
|
setDisabledState | ||||||
setDisabledState(isDisabled: boolean)
|
||||||
Defined in src/number-input/number.component.ts:337
|
||||||
Sets the disabled state through the model
Parameters :
Returns :
void
|
Public writeValue | ||||||||
writeValue(value: any)
|
||||||||
Defined in src/number-input/number.component.ts:310
|
||||||||
This is the initial value set to the component
Parameters :
Returns :
void
|
Protected _decrementLabel |
Type : Overridable
|
Default value : this.i18n.getOverridable("NUMBER.DECREMENT")
|
Defined in src/number-input/number.component.ts:296
|
Protected _incrementLabel |
Type : Overridable
|
Default value : this.i18n.getOverridable("NUMBER.INCREMENT")
|
Defined in src/number-input/number.component.ts:297
|
Protected _isFocused |
Default value : false
|
Defined in src/number-input/number.component.ts:292
|
Protected _value |
Type : number
|
Default value : 0
|
Defined in src/number-input/number.component.ts:294
|
containerClass |
Default value : true
|
Decorators :
@HostBinding('class.cds--form-item')
|
Defined in src/number-input/number.component.ts:155
|
Static numberCount |
Type : number
|
Default value : 0
|
Defined in src/number-input/number.component.ts:153
|
Variable used for creating unique ids for number input components. |
onTouched |
Type : function
|
Default value : () => {...}
|
Defined in src/number-input/number.component.ts:344
|
Called when number input is blurred. Needed to properly implement |
propagateChange |
Default value : () => {...}
|
Defined in src/number-input/number.component.ts:349
|
Method set in |
value | ||||||
getvalue()
|
||||||
Defined in src/number-input/number.component.ts:205
|
||||||
setvalue(v: any)
|
||||||
Defined in src/number-input/number.component.ts:197
|
||||||
Sets the value attribute on the
Parameters :
Returns :
void
|
decrementLabel | ||||||
getdecrementLabel()
|
||||||
Defined in src/number-input/number.component.ts:258
|
||||||
setdecrementLabel(value: string | Observable
|
||||||
Defined in src/number-input/number.component.ts:254
|
||||||
Parameters :
Returns :
void
|
incrementLabel | ||||||
getincrementLabel()
|
||||||
Defined in src/number-input/number.component.ts:267
|
||||||
setincrementLabel(value: string | Observable
|
||||||
Defined in src/number-input/number.component.ts:263
|
||||||
Parameters :
Returns :
void
|
fluidInvalid |
getfluidInvalid()
|
Defined in src/number-input/number.component.ts:276
|
fluidDisabled |
getfluidDisabled()
|
Defined in src/number-input/number.component.ts:280
|
fluidFocus |
getfluidFocus()
|
Defined in src/number-input/number.component.ts:284
|
fluidSkeleton |
getfluidSkeleton()
|
Defined in src/number-input/number.component.ts:288
|
import {
Component,
Input,
HostBinding,
EventEmitter,
Output,
TemplateRef,
HostListener
} from "@angular/core";
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms";
import { I18n, Overridable } from "carbon-components-angular/i18n";
import { Observable } from "rxjs";
/**
* Used to emit changes performed on number input components.
*/
export class NumberChange {
/**
* Contains the `Number` that has been changed.
*/
source: NumberComponent;
/**
* The value of the `Number` field encompassed in the `NumberChange` class.
*/
value: number;
}
/**
* Get started with importing the module:
*
* ```typescript
* import { NumberModule } from 'carbon-components-angular';
* ```
*
* [See demo](../../?path=/story/components-number--basic)
*/
@Component({
selector: "cds-number, ibm-number",
template: `
<label *ngIf="skeleton && label" class="cds--label cds--skeleton"></label>
<div
data-numberinput
[attr.data-invalid]="(invalid ? true : null)"
class="cds--number"
[ngClass]="{
'cds--number--light': theme === 'light',
'cds--number--nolabel': !label,
'cds--number--helpertext': helperText,
'cds--skeleton' : skeleton,
'cds--number--sm': size === 'sm',
'cds--number--md': size === 'md',
'cds--number--lg': size === 'lg'
}">
<label
*ngIf="!skeleton && label"
[for]="id"
class="cds--label"
[ngClass]="{'cds--label--disabled': disabled}">
<ng-container *ngIf="!isTemplate(label)">{{label}}</ng-container>
<ng-template *ngIf="isTemplate(label)" [ngTemplateOutlet]="label"></ng-template>
</label>
<div
class="cds--number__input-wrapper"
[ngClass]="{
'cds--number__input-wrapper--warning': warn
}">
<input
type="number"
[id]="id"
[value]="value"
[attr.min]="min"
[attr.max]="max"
[attr.step]="step"
[disabled]="disabled"
[readonly]="readonly"
[required]="required"
[attr.aria-label]="ariaLabel"
[attr.data-invalid]="invalid ? invalid : null"
[placeholder]="placeholder"
(focus)="fluid ? handleFocus($event): null"
(blur)="fluid ? handleFocus($event): null"
(change)="onNumberInputChange($event)"/>
<svg
*ngIf="!skeleton && invalid"
cdsIcon="warning--filled"
size="16"
class="cds--number__invalid">
</svg>
<svg
*ngIf="!skeleton && !invalid && warn"
cdsIcon="warning--alt--filled"
size="16"
class="cds--number__invalid cds--number__invalid--warning">
</svg>
<div *ngIf="!skeleton" class="cds--number__controls">
<button
class="cds--number__control-btn down-icon"
type="button"
[attr.disabled]="disabled ? true : null"
aria-live="polite"
aria-atomic="true"
[attr.aria-label]="getDecrementLabel() | async"
(click)="onDecrement()">
<svg cdsIcon="subtract" size="16"></svg>
</button>
<div class="cds--number__rule-divider"></div>
<button
class="cds--number__control-btn up-icon"
type="button"
[attr.disabled]="disabled ? true : null"
aria-live="polite"
aria-atomic="true"
[attr.aria-label]="getIncrementLabel() | async"
(click)="onIncrement()">
<svg cdsIcon="add" size="16"></svg>
</button>
<div class="cds--number__rule-divider"></div>
</div>
</div>
<hr *ngIf="fluid" class="cds--number-input__divider" />
<div
*ngIf="helperText && !invalid && !warn && !fluid"
class="cds--form__helper-text"
[ngClass]="{
'cds--form__helper-text--disabled': disabled
}">
<ng-container *ngIf="!isTemplate(helperText)">{{helperText}}</ng-container>
<ng-template *ngIf="isTemplate(helperText)" [ngTemplateOutlet]="helperText"></ng-template>
</div>
<div *ngIf="invalid" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(invalidText)">{{invalidText}}</ng-container>
<ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template>
</div>
<div *ngIf="!invalid && warn" class="cds--form-requirement">
<ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container>
<ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template>
</div>
</div>
`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: NumberComponent,
multi: true
}
]
})
export class NumberComponent implements ControlValueAccessor {
/**
* Variable used for creating unique ids for number input components.
*/
static numberCount = 0;
@HostBinding("class.cds--form-item") containerClass = true;
/**
* Set to `true` for readonly state.
*/
@Input() @HostBinding("class.cds--number--readonly") readonly = false;
/**
* @deprecated since v5 - Use `cdsLayer` directive instead
* `light` or `dark` number input theme.
*/
@Input() theme: "light" | "dark" = "dark";
/**
* Set to `true` for a disabled number input.
*/
@Input() disabled = false;
/**
* Set to `true` for a loading number component.
*/
@Input() skeleton = false;
/**
* Set to `true` for an invalid number component.
*/
@Input() invalid = false;
/**
* The unique id for the number component.
*/
@Input() id = `number-${NumberComponent.numberCount}`;
/**
* Sets the placeholder attribute on the `input` element.
*/
@Input() placeholder = "";
/**
* Number input field render size
*/
@Input() size: "sm" | "md" | "lg" = "md";
/**
* Reflects the required attribute of the `input` element.
*/
@Input() required: boolean;
/**
* Sets the value attribute on the `input` element.
*/
@Input() set value(v: any) {
if (v === "" || v === null) {
this._value = null;
return;
}
this._value = Number(v);
}
get value() {
return this._value;
}
/**
* Sets the min attribute on the `input` element.
*/
@Input() min = null;
/**
* Sets the max attribute on the `input` element.
*/
@Input() max = null;
/**
* Sets the text inside the `label` tag.
*/
@Input() label: string | TemplateRef<any>;
/**
* Sets the optional helper text.
*/
@Input() helperText: string | TemplateRef<any>;
/**
* Sets the invalid text.
*/
@Input() invalidText: string | TemplateRef<any>;
/**
* Sets the amount the number controls increment and decrement by.
*/
@Input() step = 1;
/**
* If `step` is a decimal, we may want precision to be set to go around floating point precision.
*/
@Input() precision: number;
/**
* Set to `true` to show a warning (contents set by warningText)
*/
@Input() warn = false;
/**
* Sets the warning text
*/
@Input() warnText: string | TemplateRef<any>;
/**
* Sets the arialabel for input
*/
@Input() ariaLabel: string;
/**
* Emits event notifying other classes when a change in state occurs in the input.
*/
@Output() change = new EventEmitter<NumberChange>();
@Input()
set decrementLabel(value: string | Observable<string>) {
this._decrementLabel.override(value);
}
get decrementLabel() {
return this._decrementLabel.value;
}
@Input()
set incrementLabel(value: string | Observable<string>) {
this._incrementLabel.override(value);
}
get incrementLabel() {
return this._incrementLabel.value;
}
/**
* Experimental: enable fluid state
*/
@HostBinding("class.cds--number-input--fluid") @Input() fluid = false;
@HostBinding("class.cds--number-input--fluid--invalid") get fluidInvalid() {
return this.fluid && this.invalid;
}
@HostBinding("class.cds--number-input--fluid--disabled") get fluidDisabled() {
return this.fluid && this.disabled;
}
@HostBinding("class.cds--number-input--fluid--focus") get fluidFocus() {
return this.fluid && this._isFocused;
}
@HostBinding("class.cds--text-input--fluid__skeleton") get fluidSkeleton() {
return this.fluid && this.skeleton;
}
protected _isFocused = false;
protected _value = 0;
protected _decrementLabel: Overridable = this.i18n.getOverridable("NUMBER.DECREMENT");
protected _incrementLabel: Overridable = this.i18n.getOverridable("NUMBER.INCREMENT");
/**
* Creates an instance of `Number`.
*/
constructor(protected i18n: I18n) {
NumberComponent.numberCount++;
}
/**
* This is the initial value set to the component
* @param value The input value.
*/
public writeValue(value: any) {
this.value = value;
}
/**
* Sets a method in order to propagate changes back to the form.
*/
public registerOnChange(fn: any) {
this.propagateChange = fn;
}
/**
* Registers a callback to be triggered when the control has been touched.
* @param fn Callback to be triggered when the number input is touched.
*/
public registerOnTouched(fn: any) {
this.onTouched = fn;
}
@HostListener("focusout")
focusOut() {
this.onTouched();
}
/**
* Sets the disabled state through the model
*/
setDisabledState(isDisabled: boolean) {
this.disabled = isDisabled;
}
/**
* Called when number input is blurred. Needed to properly implement `ControlValueAccessor`.
*/
onTouched: () => any = () => { };
/**
* Method set in `registerOnChange` to propagate changes back to the form.
*/
propagateChange = (_: any) => { };
/**
* Adds `step` to the current `value`.
*/
onIncrement(): void {
// if max is set and value + step is greater than max, set value to max
// example: max = 100, step = 10, value = 95 , value + step = 105, value will be set to 100 (max) instead of 105
if (this.max !== null && this.value + this.step > this.max) {
this.value = this.max;
this.emitChangeEvent();
return;
}
// if min is set and value + step is less than min, set value to min
// example: min = 5, step = 2, value = 0, value + step = 2, value will be set to 5 (min) instead of 2
if (this.min !== null && this.value + this.step < this.min) {
this.value = this.min;
this.emitChangeEvent();
return;
}
// if max is not set or value + step is less than max, increment value by step
if (this.max === null || this.value + this.step <= this.max) {
this.value += this.step;
this.value = parseFloat(this.value.toPrecision(this.precision));
this.emitChangeEvent();
}
}
/**
* Subtracts `step` to the current `value`.
*/
onDecrement(): void {
// if max is set and value - step is greater than max, set value to max
// example: max = 15, step = 2, value = 20, value - step = 18, value will be set to 15 (max) instead of 18
if (this.max !== null && this.value - this.step > this.max) {
this.value = this.max;
this.emitChangeEvent();
return;
}
// if min is set and value - step is less than min, set value to min
// example: min = 5, step = 2, value = 6, value - step = 4, value will be set to 5 (min) instead of 4
if (this.min !== null && this.value - this.step < this.min) {
this.value = this.min;
this.emitChangeEvent();
return;
}
// if min is not set or value - step is greater than min, decrement value by step
if (this.min === null || this.value - this.step >= this.min) {
this.value -= this.step;
this.value = parseFloat(this.value.toPrecision(this.precision));
this.emitChangeEvent();
}
}
getDecrementLabel(): Observable<string> {
return this._decrementLabel.subject;
}
getIncrementLabel(): Observable<string> {
return this._incrementLabel.subject;
}
/**
* Creates a class of `NumberChange` to emit the change in the `Number`.
*/
emitChangeEvent(): void {
let event = new NumberChange();
event.source = this;
event.value = this.value;
this.change.emit(event);
this.propagateChange(this.value);
}
onNumberInputChange(event) {
this.value = event.target.value;
this.emitChangeEvent();
}
public isTemplate(value) {
return value instanceof TemplateRef;
}
handleFocus(event: FocusEvent) {
if ("type" in event.target && (<HTMLInputElement>event.target).type === "button") {
this._isFocused = false;
} else {
this._isFocused = event.type === "focus";
}
}
}
export { NumberComponent as Number };