carbon-components-angular
Version:
Next generation components
815 lines (694 loc) • 27 kB
HTML
<html class="no-js" lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>carbon-components-angular documentation</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="../images/favicon.ico">
<link rel="stylesheet" href="../styles/style.css">
<link rel="stylesheet" href="../styles/dark.css">
<style>
footer.carbon {
position: absolute;
bottom: 0;
width: 100%;
z-index: 9999;
}
#root > div {
/*
* Subtracting the height of the footer to prevent
* overlaying the footer ontop of content
*/
height: calc(100vh - 48px);
}
</style>
</head>
<body>
<script>
// Blocking script to avoid flickering dark mode
// Dark mode toggle button
var useDark = window.matchMedia('(prefers-color-scheme: dark)');
var darkModeState = useDark.matches;
var $darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input');
var $darkModeToggles = document.querySelectorAll('.dark-mode-switch');
var darkModeStateLocal = localStorage.getItem('compodoc_darkmode-state');
function checkToggle(check) {
for (var i = 0; i < $darkModeToggleSwitchers.length; i++) {
$darkModeToggleSwitchers[i].checked = check;
}
}
function toggleDarkMode(state) {
if (window.localStorage) {
localStorage.setItem('compodoc_darkmode-state', state);
}
checkToggle(state);
const hasClass = document.body.classList.contains('dark');
if (state) {
for (var i = 0; i < $darkModeToggles.length; i++) {
$darkModeToggles[i].classList.add('dark');
}
if (!hasClass) {
document.body.classList.add('dark');
}
} else {
for (var i = 0; i < $darkModeToggles.length; i++) {
$darkModeToggles[i].classList.remove('dark');
}
if (hasClass) {
document.body.classList.remove('dark');
}
}
}
useDark.addEventListener('change', function (evt) {
toggleDarkMode(evt.matches);
});
if (darkModeStateLocal) {
darkModeState = darkModeStateLocal === 'true';
}
toggleDarkMode(darkModeState);
</script>
<div class="navbar navbar-default navbar-fixed-top d-md-none p-0">
<div class="d-flex">
<a href="../" class="navbar-brand">carbon-components-angular documentation</a>
<button type="button" class="btn btn-default btn-menu ion-ios-menu" id="btn-menu"></button>
</div>
</div>
<div class="xs-menu menu" id="mobile-menu">
<div id="book-search-input" role="search"><input type="text" placeholder="Type to search"></div> <compodoc-menu></compodoc-menu>
</div>
<div class="container-fluid main">
<div class="row main">
<div class="d-none d-md-block menu">
<compodoc-menu mode="normal"></compodoc-menu>
</div>
<!-- START CONTENT -->
<div class="content class">
<div class="content-data">
<ol class="breadcrumb">
<li class="breadcrumb-item">Classes</li>
<li class="breadcrumb-item" >NumberChange</li>
</ol>
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item">
<a href="#info"
class="nav-link"
class="nav-link active"
role="tab" id="info-tab" data-bs-toggle="tab" data-link="info">Info</a>
</li>
<li class="nav-item">
<a href="#source"
class="nav-link"
role="tab" id="source-tab" data-bs-toggle="tab" data-link="source">Source</a>
</li>
</ul>
<div class="tab-content">
<div class="tab-pane fade active in" id="info">
<p class="comment">
<h3>File</h3>
</p>
<p class="comment">
<code>src/number-input/number.component.ts</code>
</p>
<p class="comment">
<h3>Description</h3>
</p>
<p class="comment">
<p>Used to emit changes performed on number input components.</p>
</p>
<section data-compodoc="block-index">
<h3 id="index">Index</h3>
<table class="table table-sm table-bordered index-table">
<tbody>
<tr>
<td class="col-md-4">
<h6><b>Properties</b></h6>
</td>
</tr>
<tr>
<td class="col-md-4">
<ul class="index-list">
<li>
<a href="#source" >source</a>
</li>
<li>
<a href="#value" >value</a>
</li>
</ul>
</td>
</tr>
</tbody>
</table>
</section>
<section data-compodoc="block-properties">
<h3 id="inputs">
Properties
</h3>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="source"></a>
<span class="name">
<span ><b>source</b></span>
<a href="#source"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<i>Type : </i> <code><a href="../components/NumberComponent.html" target="_self" >NumberComponent</a></code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="22" class="link-to-prism">src/number-input/number.component.ts:22</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>Contains the <code>Number</code> that has been changed.</p>
</div>
</td>
</tr>
</tbody>
</table>
<table class="table table-sm table-bordered">
<tbody>
<tr>
<td class="col-md-4">
<a name="value"></a>
<span class="name">
<span ><b>value</b></span>
<a href="#value"><span class="icon ion-ios-link"></span></a>
</span>
</td>
</tr>
<tr>
<td class="col-md-4">
<i>Type : </i> <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/number" target="_blank" >number</a></code>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-line">Defined in <a href="" data-line="26" class="link-to-prism">src/number-input/number.component.ts:26</a></div>
</td>
</tr>
<tr>
<td class="col-md-4">
<div class="io-description"><p>The value of the <code>Number</code> field encompassed in the <code>NumberChange</code> class.</p>
</div>
</td>
</tr>
</tbody>
</table>
</section>
</div>
<div class="tab-pane fade tab-source-code" id="source">
<pre class="line-numbers compodoc-sourcecode"><code class="language-typescript">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 };
</code></pre>
</div>
</div>
</div><div class="search-results">
<div class="has-results">
<h1 class="search-results-title"><span class='search-results-count'></span> results matching "<span class='search-query'></span>"</h1>
<ul class="search-results-list"></ul>
</div>
<div class="no-results">
<h1 class="search-results-title">No results matching "<span class='search-query'></span>"</h1>
</div>
</div>
</div>
<!-- END CONTENT -->
</div>
</div>
<label class="dark-mode-switch">
<input type="checkbox">
<span class="slider">
<svg class="slider-icon" viewBox="0 0 24 24" fill="none" height="20" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" width="20" xmlns="http://www.w3.org/2000/svg">
<path d="M21 12.79A9 9 0 1111.21 3 7 7 0 0021 12.79z"></path>
</svg>
</span>
</label>
<script>
var COMPODOC_CURRENT_PAGE_DEPTH = 1;
var COMPODOC_CURRENT_PAGE_CONTEXT = 'class';
var COMPODOC_CURRENT_PAGE_URL = 'NumberChange.html';
var MAX_SEARCH_RESULTS = 15;
</script>
<script>
$darkModeToggleSwitchers = document.querySelectorAll('.dark-mode-switch input');
checkToggle(darkModeState);
if ($darkModeToggleSwitchers.length > 0) {
for (var i = 0; i < $darkModeToggleSwitchers.length; i++) {
$darkModeToggleSwitchers[i].addEventListener('change', function (event) {
darkModeState = !darkModeState;
toggleDarkMode(darkModeState);
});
}
}
</script>
<script src="../js/libs/custom-elements.min.js"></script>
<script src="../js/libs/lit-html.js"></script>
<script src="../js/menu-wc.js" defer></script>
<script nomodule src="../js/menu-wc_es5.js" defer></script>
<script src="../js/libs/bootstrap-native.js"></script>
<script src="../js/libs/es6-shim.min.js"></script>
<script src="../js/libs/EventDispatcher.js"></script>
<script src="../js/libs/promise.min.js"></script>
<script src="../js/libs/zepto.min.js"></script>
<script src="../js/compodoc.js"></script>
<script src="../js/tabs.js"></script>
<script src="../js/menu.js"></script>
<script src="../js/libs/clipboard.min.js"></script>
<script src="../js/libs/prism.js"></script>
<script src="../js/sourceCode.js"></script>
<script src="../js/search/search.js"></script>
<script src="../js/search/lunr.min.js"></script>
<script src="../js/search/search-lunr.js"></script>
<script src="../js/search/search_index.js"></script>
<script src="../js/lazy-load-graphs.js"></script>
<footer class="carbon">
<dds-footer-container key="footer" disable-locale-button="true" size="micro" />
</footer>
<script
key="8"
type="module"
src="https://1.www.s81c.com/common/carbon-for-ibm-dotcom/tag/v1/latest/footer.min.js">
</script>
<!-- Storybook override -->
<script>
document.title = "Carbon Components Angular";
</script>
<script
src="//1.www.s81c.com/common/stats/ibm-common.js"
type="text/javascript"
async="async">
</script>
</body>
</html>