@engie-group/fluid-design-system-angular
Version:
Fluid Design System Angular
220 lines (192 loc) • 5.07 kB
text/typescript
import { CommonModule } from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ContentChildren,
ElementRef,
EventEmitter,
Input,
OnDestroy,
Output,
QueryList,
ViewChild
} from '@angular/core';
import { ControlValueAccessor } from '@angular/forms';
import { Subject, takeUntil } from 'rxjs';
import { Utils } from '../../utils/utils.util';
import { SegmentedControlButtonComponent } from '../segmented-control-button/segmented-control-button.component';
import { SegmentedControlSize } from './segmented-control.model';
export class SegmentedControlComponent implements ControlValueAccessor, AfterViewInit, OnDestroy {
private readonly segmentedControlClass = 'nj-segmented-control';
/**
* @ignore
*/
private unsubscribe: Subject<void> = new Subject<void>();
/**
* @ignore
*/
private _onChange = (_: any): void => {};
/**
* @ignore
*/
private _onTouched = (): void => {};
/**
* @ignore
*/
private _isDisabled: boolean;
/**
* @ignore
*/
private _value: string;
/**
* @ignore
*/
public segmentedButtons: SegmentedControlButtonComponent[];
/**
* Selected value
*/
set value(value: string) {
this._value = value;
this.setActive(value);
}
get value(): string {
return this._value;
}
/**
* Selected aria label
*/
ariaLabel: string;
/**
* Overrides disabled state on all buttons
*/
set isDisabled(value: boolean) {
this._isDisabled = value;
this.setButtonsIsDisabled();
}
get isDisabled(): boolean {
return this._isDisabled;
}
/**
* Segmented Control size
*/
size: SegmentedControlSize = 'md';
/**
* @ignore
*/
segmentedButtonsList: QueryList<SegmentedControlButtonComponent>;
/**
* @ignore
*/
segmentedControl: ElementRef<HTMLDivElement>;
/**
* Output that emits value change
*/
valueChange: EventEmitter<string> = new EventEmitter<string>();
constructor(private cdr: ChangeDetectorRef) {}
ngAfterViewInit() {
// A render is being done after view init so setTimeout allows us to delay any attribute modification
// in the call stack, so it can be taken account on next render only
setTimeout(() => {
this.segmentedButtons = this.segmentedButtonsList?.toArray();
this.setButtonsIsDisabled();
this.initializeClickListener();
if (this.value) {
this.setActive(this.value);
}
});
}
private setButtonsIsDisabled() {
if (!Utils.isUndefinedOrNull(this.isDisabled) && this.segmentedButtons) {
for (const segmentedButton of this.segmentedButtons) {
segmentedButton.setIsDisabled(this.isDisabled);
}
}
}
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
/**
* @ignore
*/
private initializeClickListener() {
if (Utils.isUndefinedOrNull(this.segmentedButtons)) {
return;
}
this.segmentedButtons.forEach((button, value) => {
button.buttonClick.pipe(takeUntil(this.unsubscribe)).subscribe((_) => {
button.isSelected = true;
this.writeValue(button.value);
});
});
}
private setActive(buttonValue: string) {
if (!this.segmentedButtons) {
return;
}
for (const button of this.segmentedButtons) {
if (button?.value === buttonValue) {
button.setIsSelected(true);
const selectedBoundingRect = button.getClientBoundingRect();
const segmentedControlBoundingRect = this.segmentedControl.nativeElement.getBoundingClientRect();
const segmentedControlStyle = this.segmentedControl?.nativeElement?.style;
segmentedControlStyle.setProperty('--nj-sc-btn-selected-width', `${selectedBoundingRect.width}px`);
segmentedControlStyle.setProperty(
'--nj-sc-btn-selected-right',
`${segmentedControlBoundingRect.right - selectedBoundingRect.right}px`
);
} else {
button.setIsSelected(false);
}
}
}
/**
* @ignore
*/
getSizeClass(): string {
if (!this.size || this.size === 'md') {
return;
}
return `${this.segmentedControlClass}--${this.size}`;
}
/**
* @ignore
*/
writeValue(value: any): void {
if (value === this.value) {
return;
}
this.setActive(value);
this.value = value;
}
/**
* @ignore
*/
registerOnChange(fn: any): void {
this._onChange = fn;
}
/**
* @ignore
*/
registerOnTouched(fn: any): void {
this._onTouched = fn;
}
/**
* @ignore
*/
setDisabledState?(isDisabled: boolean): void {
this.isDisabled = isDisabled;
this.cdr.markForCheck();
}
}