File

src/number-input/number.component.ts

Description

Get started with importing the module:

Example :
import { NumberModule } from 'carbon-components-angular';

See demo

Implements

ControlValueAccessor

Metadata

Index

Properties
Methods
Inputs
Outputs
HostBindings
HostListeners
Accessors

Constructor

constructor(i18n: I18n)

Creates an instance of Number.

Parameters :
Name Type Optional
i18n I18n No

Inputs

ariaLabel
Type : string

Sets the arialabel for input

decrementLabel
Type : string | Observable
disabled
Type : boolean
Default value : false

Set to true for a disabled number input.

fluid
Type : boolean
Default value : false

Experimental: enable fluid state

helperText
Type : string | TemplateRef<any>

Sets the optional helper text.

id
Type : string
Default value : `number-${NumberComponent.numberCount}`

The unique id for the number component.

incrementLabel
Type : string | Observable
invalid
Type : boolean
Default value : false

Set to true for an invalid number component.

invalidText
Type : string | TemplateRef<any>

Sets the invalid text.

label
Type : string | TemplateRef<any>

Sets the text inside the label tag.

max
Type : any
Default value : null

Sets the max attribute on the input element.

min
Type : any
Default value : null

Sets the min attribute on the input element.

placeholder
Type : string
Default value : ""

Sets the placeholder attribute on the input element.

precision
Type : number

If step is a decimal, we may want precision to be set to go around floating point precision.

readonly
Type : boolean
Default value : false

Set to true for readonly state.

required
Type : boolean

Reflects the required attribute of the input element.

size
Type : "sm" | "md" | "lg"
Default value : "md"

Number input field render size

skeleton
Type : boolean
Default value : false

Set to true for a loading number component.

step
Type : number
Default value : 1

Sets the amount the number controls increment and decrement by.

theme
Type : "light" | "dark"
Default value : "dark"
value
Type : any

Sets the value attribute on the input element.

warn
Type : boolean
Default value : false

Set to true to show a warning (contents set by warningText)

warnText
Type : string | TemplateRef<any>

Sets the warning text

Outputs

change
Type : EventEmitter

Emits event notifying other classes when a change in state occurs in the input.

HostBindings

class.cds--form-item
Type : boolean
Default value : true
class.cds--number-input--fluid--disabled
Type : boolean
class.cds--number-input--fluid--focus
Type : boolean
class.cds--number-input--fluid--invalid
Type : boolean
class.cds--text-input--fluid__skeleton
Type : boolean

HostListeners

focusout
focusout()

Methods

emitChangeEvent
emitChangeEvent()

Creates a class of NumberChange to emit the change in the Number.

Returns : void
focusOut
focusOut()
Decorators :
@HostListener('focusout')
Returns : void
getDecrementLabel
getDecrementLabel()
Returns : Observable<string>
getIncrementLabel
getIncrementLabel()
Returns : Observable<string>
handleFocus
handleFocus(event: FocusEvent)
Parameters :
Name Type Optional
event FocusEvent No
Returns : void
Public isTemplate
isTemplate(value)
Parameters :
Name Optional
value No
Returns : boolean
onDecrement
onDecrement()

Subtracts step to the current value.

Returns : void
onIncrement
onIncrement()

Adds step to the current value.

Returns : void
onNumberInputChange
onNumberInputChange(event)
Parameters :
Name Optional
event No
Returns : void
Public registerOnChange
registerOnChange(fn: any)

Sets a method in order to propagate changes back to the form.

Parameters :
Name Type Optional
fn any No
Returns : void
Public registerOnTouched
registerOnTouched(fn: any)

Registers a callback to be triggered when the control has been touched.

Parameters :
Name Type Optional Description
fn any No

Callback to be triggered when the number input is touched.

Returns : void
setDisabledState
setDisabledState(isDisabled: boolean)

Sets the disabled state through the model

Parameters :
Name Type Optional
isDisabled boolean No
Returns : void
Public writeValue
writeValue(value: any)

This is the initial value set to the component

Parameters :
Name Type Optional Description
value any No

The input value.

Returns : void

Properties

Protected _decrementLabel
Type : Overridable
Default value : this.i18n.getOverridable("NUMBER.DECREMENT")
Protected _incrementLabel
Type : Overridable
Default value : this.i18n.getOverridable("NUMBER.INCREMENT")
Protected _isFocused
Default value : false
Protected _value
Type : number
Default value : 0
containerClass
Default value : true
Decorators :
@HostBinding('class.cds--form-item')
Static numberCount
Type : number
Default value : 0

Variable used for creating unique ids for number input components.

onTouched
Type : function
Default value : () => {...}

Called when number input is blurred. Needed to properly implement ControlValueAccessor.

propagateChange
Default value : () => {...}

Method set in registerOnChange to propagate changes back to the form.

Accessors

value
getvalue()
setvalue(v: any)

Sets the value attribute on the input element.

Parameters :
Name Type Optional
v any No
Returns : void
decrementLabel
getdecrementLabel()
setdecrementLabel(value: string | Observable)
Parameters :
Name Type Optional
value string | Observable<string> No
Returns : void
incrementLabel
getincrementLabel()
setincrementLabel(value: string | Observable)
Parameters :
Name Type Optional
value string | Observable<string> No
Returns : void
fluidInvalid
getfluidInvalid()
fluidDisabled
getfluidDisabled()
fluidFocus
getfluidFocus()
fluidSkeleton
getfluidSkeleton()
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 };
Legend
Html element
Component
Html element with directive

results matching ""

    No results matching ""