UNPKG

carbon-components-angular

Version:
693 lines (686 loc) 24 kB
import * as i0 from '@angular/core'; import { EventEmitter, Component, Input, Output, HostBinding, TemplateRef, ContentChildren, forwardRef, HostListener, NgModule } from '@angular/core'; import { NG_VALUE_ACCESSOR, FormsModule } from '@angular/forms'; import * as i1 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i2 from 'carbon-components-angular/icon'; import { IconModule } from 'carbon-components-angular/icon'; /** * Used to emit changes performed on a `Radio`. */ class RadioChange { constructor(source, value) { this.source = source; this.value = value; } } /** * class: Radio (extends Checkbox) * * selector: `n-radio` * * source: `src/forms/radio.component.ts` * * ```html * <cds-radio [(ngModel)]="radioState">Radio</cds-radio> * ``` * * Also see: [`RadioGroup`](#cds-radio-group) */ class Radio { constructor() { this.checked = false; this.name = ""; this.disabled = false; this.labelPlacement = "right"; /** * Sets the HTML required attribute */ this.required = false; /** * Set to `true` for a loading table. */ this.skeleton = false; /** * The id for the `Radio`. */ this.id = `radio-${Radio.radioCount++}`; /** * emits when the state of the radio changes */ this.change = new EventEmitter(); this.hostClass = true; /** * Reflects whether or not the input is disabled at `RadioGroup` level. */ this.disabledFromGroup = false; this._labelledby = ""; /** * Handler provided by the `RadioGroup` to bubble events up */ this.radioChangeHandler = (event) => { }; } set ariaLabelledby(value) { this._labelledby = value; } get ariaLabelledby() { if (this._labelledby) { return this._labelledby; } return `label-${this.id}`; } get labelLeft() { return this.labelPlacement === "left"; } /** * Synchronizes with the `RadioGroup` in the event of a changed `Radio`. * Emits the changes of both the `RadioGroup` and `Radio`. */ onChange(event) { event.stopPropagation(); } onClick(event) { this.checked = event.target.checked; const radioEvent = new RadioChange(this, this.value); this.change.emit(radioEvent); this.radioChangeHandler(radioEvent); } /** * Method called by `RadioGroup` with a callback function to bubble `RadioChange` events * @param fn callback that expects a `RadioChange` as an argument */ registerRadioChangeHandler(fn) { this.radioChangeHandler = fn; } setDisabledFromGroup(disabled) { this.disabledFromGroup = disabled; } } /** * Used to dynamically create unique ids for the `Radio`. */ Radio.radioCount = 0; Radio.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Radio, deps: [], target: i0.ɵɵFactoryTarget.Component }); Radio.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: Radio, selector: "cds-radio, ibm-radio", inputs: { checked: "checked", name: "name", disabled: "disabled", labelPlacement: "labelPlacement", ariaLabelledby: "ariaLabelledby", ariaLabel: "ariaLabel", required: "required", value: "value", skeleton: "skeleton", id: "id" }, outputs: { change: "change" }, host: { properties: { "class.cds--radio-button-wrapper": "this.hostClass", "class.cds--radio-button-wrapper--label-left": "this.labelLeft" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: Radio, multi: true } ], ngImport: i0, template: ` <input *ngIf="!skeleton" class="cds--radio-button" type="radio" [checked]="checked" [disabled]="disabled || disabledFromGroup" [name]="name" [id]="id" [required]="required" [attr.value]="value" [attr.aria-labelledby]="ariaLabelledby" (change)="onChange($event)" (click)="onClick($event)"> <div *ngIf="skeleton" class="cds--radio-button cds--skeleton"></div> <label class="cds--radio-button__label" [attr.aria-label]="ariaLabel" [ngClass]="{ 'cds--skeleton': skeleton }" [for]="id" id="label-{{id}}"> <span class="cds--radio-button__appearance"></span> <ng-content></ng-content> </label> `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: Radio, decorators: [{ type: Component, args: [{ selector: "cds-radio, ibm-radio", template: ` <input *ngIf="!skeleton" class="cds--radio-button" type="radio" [checked]="checked" [disabled]="disabled || disabledFromGroup" [name]="name" [id]="id" [required]="required" [attr.value]="value" [attr.aria-labelledby]="ariaLabelledby" (change)="onChange($event)" (click)="onClick($event)"> <div *ngIf="skeleton" class="cds--radio-button cds--skeleton"></div> <label class="cds--radio-button__label" [attr.aria-label]="ariaLabel" [ngClass]="{ 'cds--skeleton': skeleton }" [for]="id" id="label-{{id}}"> <span class="cds--radio-button__appearance"></span> <ng-content></ng-content> </label> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: Radio, multi: true } ] }] }], propDecorators: { checked: [{ type: Input }], name: [{ type: Input }], disabled: [{ type: Input }], labelPlacement: [{ type: Input }], ariaLabelledby: [{ type: Input }], ariaLabel: [{ type: Input }], required: [{ type: Input }], value: [{ type: Input }], skeleton: [{ type: Input }], id: [{ type: Input }], change: [{ type: Output }], hostClass: [{ type: HostBinding, args: ["class.cds--radio-button-wrapper"] }], labelLeft: [{ type: HostBinding, args: ["class.cds--radio-button-wrapper--label-left"] }] } }); /** * Get started with importing the module: * * ```typescript * import { RadioModule } from 'carbon-components-angular'; * ``` * * Ex: * * ```html * <cds-radio-group [(ngModel)]="radio"> * <cds-radio *ngFor="let one of manyRadios" [value]="one"> * Radio {{one}} * </cds-radio> * </cds-radio-group> * * Radio selected: {{radio}} * ``` * * ```ts * const manyRadios = ["one", "two", "three", "four", "five", "six"]; * ``` * * [See demo](../../?path=/story/components-radio--basic) */ class RadioGroup { constructor() { this.orientation = "horizontal"; this.labelPlacement = "right"; /** * Set to `true` to show the invalid state. */ this.invalid = false; /** * Set to `true` to show a warning (contents set by warnText) */ this.warn = false; /** * Emits event notifying other classes of a change using a `RadioChange` class. */ this.change = new EventEmitter(); /** * Binds 'cds--form-item' value to the class for `RadioGroup`. */ this.radioButtonGroupClass = true; /** * To track whether the `RadioGroup` has been initialized. */ this.isInitialized = false; /** * Reflects whether or not the input is disabled and cannot be selected. */ this._disabled = false; /** * Reflects whether or not the dropdown is loading. */ this._skeleton = false; /** * The value of the selected option within the `RadioGroup`. */ this._value = null; /** * The `Radio` within the `RadioGroup` that is selected. */ this._selected = null; /** * The name attribute associated with the `RadioGroup`. */ this._name = `radio-group-${RadioGroup.radioGroupCount++}`; /** * Needed to properly implement ControlValueAccessor. */ this.onTouched = () => { }; /** * Method set in registerOnChange to propagate changes back to the form. */ this.propagateChange = (_) => { }; } /** * Sets the passed in `Radio` item as the selected input within the `RadioGroup`. */ set selected(selected) { const alreadySelected = (this._selected && this._selected.value) === (selected && selected.value); if (alreadySelected) { // no need to redo return; } if (this._selected) { this._selected.checked = false; } this._selected = selected; this.value = selected ? selected.value : null; this.checkSelectedRadio(); } /** * Returns the `Radio` that is selected within the `RadioGroup`. */ get selected() { return this._selected; } /** * Sets the value/state of the selected `Radio` within the `RadioGroup` to the passed in value. */ set value(newValue) { if (this._value !== newValue) { this._value = newValue; this.updateSelectedRadioFromValue(); this.checkSelectedRadio(); } } /** * Returns the value/state of the selected `Radio` within the `RadioGroup`. */ get value() { return this._value; } /** * Replaces the name associated with the `RadioGroup` with the provided parameter. */ set name(name) { this._name = name; this.updateRadios(); } /** * Returns the associated name of the `RadioGroup`. */ get name() { return this._name; } /** * Set to true to disable the whole radio group */ set disabled(disabled) { this._disabled = disabled; this.updateRadios(); } /** * Returns the disabled value for the `RadioGroup`. */ get disabled() { return this._disabled; } /** * Returns the skeleton value in the `RadioGroup` if there is one. */ get skeleton() { return this._skeleton; } /** * Sets the skeleton value for all `Radio` to the skeleton value of `RadioGroup`. */ set skeleton(value) { this._skeleton = value; this.updateChildren(); } /** * Updates the selected `Radio` to be checked (selected). */ checkSelectedRadio() { if (this.selected && !this._selected.checked) { this.selected.checked = true; } } /** * Use the value of the `RadioGroup` to update the selected radio to the right state (selected state). */ updateSelectedRadioFromValue() { let alreadySelected = this._selected != null && this._selected.value === this._value; if (this.radios && !alreadySelected) { if (this.selected && this.value) { this.selected.checked = false; } this._selected = null; this.radios.forEach(radio => { if (radio.checked || radio.value === this._value) { this._selected = radio; } }); if (this.selected && !this.value) { this._value = this.selected.value; } } } /** * `ControlValueAccessor` method to programmatically disable the `RadioGroup`. * * ex: `this.formGroup.get("myRadioGroup").disable();` * * @param isDisabled `true` to disable the inputs */ setDisabledState(isDisabled) { this.disabled = isDisabled; } /** * Creates a class of `RadioChange` to emit the change in the `RadioGroup`. */ emitChangeEvent(event) { this.change.emit(event); this.propagateChange(event.value); this.onTouched(); } /** * Synchronizes radio properties. */ updateRadios() { if (this.radios) { setTimeout(() => { this.radios.forEach(radio => { radio.name = this.name; radio.setDisabledFromGroup(this.disabled); if (this.labelPlacement === "left") { radio.labelPlacement = "left"; } }); }); } } /** * Updates the value of the `RadioGroup` using the provided parameter. */ writeValue(value) { this.value = value; setTimeout(() => { this.updateSelectedRadioFromValue(); this.checkSelectedRadio(); }); } ngAfterContentInit() { this.radios.changes.subscribe(() => { this.updateRadios(); this.updateRadioChangeHandler(); }); this.updateChildren(); this.updateRadioChangeHandler(); } ngAfterViewInit() { this.updateRadios(); } /** * Used to set method to propagate changes back to the form. */ registerOnChange(fn) { this.propagateChange = fn; } /** * Registers a callback to be triggered when the control has been touched. * @param fn Callback to be triggered when the checkbox is touched. */ registerOnTouched(fn) { this.onTouched = fn; } focusOut() { this.onTouched(); } isTemplate(value) { return value instanceof TemplateRef; } updateChildren() { if (this.radios) { this.radios.forEach(child => child.skeleton = this.skeleton); } } updateRadioChangeHandler() { this.radios.forEach(radio => { radio.registerRadioChangeHandler((event) => { if ((this.selected && this.selected.value) === event.value) { // no need to redo return; } // deselect previous radio if (this.selected) { this.selected.checked = false; } // update selected and value from the event this._selected = event.source; this._value = event.value; // bubble the event this.emitChangeEvent(event); }); }); } } /** * Used for creating the `RadioGroup` 'name' property dynamically. */ RadioGroup.radioGroupCount = 0; RadioGroup.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RadioGroup, deps: [], target: i0.ɵɵFactoryTarget.Component }); RadioGroup.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: RadioGroup, selector: "cds-radio-group, ibm-radio-group", inputs: { selected: "selected", value: "value", name: "name", disabled: "disabled", skeleton: "skeleton", orientation: "orientation", labelPlacement: "labelPlacement", legend: "legend", ariaLabel: "ariaLabel", ariaLabelledby: "ariaLabelledby", helperText: "helperText", invalid: "invalid", invalidText: "invalidText", warn: "warn", warnText: "warnText" }, outputs: { change: "change" }, host: { listeners: { "focusout": "focusOut()" }, properties: { "class.cds--form-item": "this.radioButtonGroupClass" } }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: RadioGroup, multi: true } ], queries: [{ propertyName: "radios", predicate: i0.forwardRef(function () { return Radio; }) }], ngImport: i0, template: ` <fieldset class="cds--radio-button-group" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledby" [ngClass]="{ 'cds--radio-button-group--vertical': orientation === 'vertical', 'cds--radio-button-group--label-left': labelPlacement === 'left', 'cds--radio-button-group--invalid': invalid, 'cds--radio-button-group--warning': !invalid && warn }" [attr.data-invalid]="invalid ? true : null"> <legend *ngIf="legend" class="cds--label"> <ng-template *ngIf="isTemplate(legend); else legendLabel;" [ngTemplateOutlet]="legend"></ng-template> <ng-template #legendLabel>{{legend}}</ng-template> </legend> <ng-content></ng-content> </fieldset> <div class="cds--radio-button__validation-msg"> <ng-container *ngIf="invalid"> <svg cdsIcon="warning--filled" size="16" class="cds--radio-button__invalid-icon"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(invalidText)">{{ invalidText }}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> </ng-container> <ng-container *ngIf="!invalid && warn"> <svg cdsIcon="warning--alt--filled" class="cds--radio-button__invalid-icon cds--radio-button__invalid-icon--warning" size="16"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </div> <div *ngIf="helperText && !invalid && !warn" 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> `, isInline: true, dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2.IconDirective, selector: "[cdsIcon], [ibmIcon]", inputs: ["ibmIcon", "cdsIcon", "size", "title", "ariaLabel", "ariaLabelledBy", "ariaHidden", "isFocusable"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RadioGroup, decorators: [{ type: Component, args: [{ selector: "cds-radio-group, ibm-radio-group", template: ` <fieldset class="cds--radio-button-group" [attr.aria-label]="ariaLabel" [attr.aria-labelledby]="ariaLabelledby" [ngClass]="{ 'cds--radio-button-group--vertical': orientation === 'vertical', 'cds--radio-button-group--label-left': labelPlacement === 'left', 'cds--radio-button-group--invalid': invalid, 'cds--radio-button-group--warning': !invalid && warn }" [attr.data-invalid]="invalid ? true : null"> <legend *ngIf="legend" class="cds--label"> <ng-template *ngIf="isTemplate(legend); else legendLabel;" [ngTemplateOutlet]="legend"></ng-template> <ng-template #legendLabel>{{legend}}</ng-template> </legend> <ng-content></ng-content> </fieldset> <div class="cds--radio-button__validation-msg"> <ng-container *ngIf="invalid"> <svg cdsIcon="warning--filled" size="16" class="cds--radio-button__invalid-icon"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(invalidText)">{{ invalidText }}</ng-container> <ng-template *ngIf="isTemplate(invalidText)" [ngTemplateOutlet]="invalidText"></ng-template> </div> </ng-container> <ng-container *ngIf="!invalid && warn"> <svg cdsIcon="warning--alt--filled" class="cds--radio-button__invalid-icon cds--radio-button__invalid-icon--warning" size="16"> </svg> <div class="cds--form-requirement"> <ng-container *ngIf="!isTemplate(warnText)">{{warnText}}</ng-container> <ng-template *ngIf="isTemplate(warnText)" [ngTemplateOutlet]="warnText"></ng-template> </div> </ng-container> </div> <div *ngIf="helperText && !invalid && !warn" 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> `, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: RadioGroup, multi: true } ] }] }], propDecorators: { selected: [{ type: Input }], value: [{ type: Input }], name: [{ type: Input }], disabled: [{ type: Input }], skeleton: [{ type: Input }], orientation: [{ type: Input }], labelPlacement: [{ type: Input }], legend: [{ type: Input }], ariaLabel: [{ type: Input }], ariaLabelledby: [{ type: Input }], helperText: [{ type: Input }], invalid: [{ type: Input }], invalidText: [{ type: Input }], warn: [{ type: Input }], warnText: [{ type: Input }], change: [{ type: Output }], radios: [{ type: ContentChildren, args: [forwardRef(() => Radio)] }], radioButtonGroupClass: [{ type: HostBinding, args: ["class.cds--form-item"] }], focusOut: [{ type: HostListener, args: ["focusout"] }] } }); // modules class RadioModule { } RadioModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RadioModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); RadioModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.3.0", ngImport: i0, type: RadioModule, declarations: [Radio, RadioGroup], imports: [CommonModule, FormsModule, IconModule], exports: [Radio, RadioGroup] }); RadioModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RadioModule, imports: [CommonModule, FormsModule, IconModule] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: RadioModule, decorators: [{ type: NgModule, args: [{ declarations: [ Radio, RadioGroup ], exports: [ Radio, RadioGroup ], imports: [ CommonModule, FormsModule, IconModule ] }] }] }); /** * Generated bundle index. Do not edit. */ export { Radio, RadioChange, RadioGroup, RadioModule }; //# sourceMappingURL=carbon-components-angular-radio.mjs.map