@engie-group/fluid-design-system-angular
Version:
Fluid Design System Angular
198 lines (172 loc) • 4.01 kB
text/typescript
import { CommonModule } from '@angular/common';
import {
AfterViewInit,
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
ElementRef,
forwardRef,
inject,
Input,
OnDestroy,
ViewChild
} from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { BehaviorSubject, Subject, takeUntil } from 'rxjs';
import { Utils } from '../../utils/utils.util';
export class SliderComponent implements AfterViewInit, OnDestroy, ControlValueAccessor {
private _initialValue: number;
private _currentValue: number;
private _max = 100;
private _min = 0;
private inputValue$ = new BehaviorSubject<number>(this._min);
private unsubscribe = new Subject<void>();
private cdr = inject(ChangeDetectorRef);
/**
* @ignore
*/
private _onChange = (_: any): void => {};
/**
* @ignore
*/
protected _onTouched = (): void => {};
/**
* Slider Id, required if label is set
*/
sliderId?: string;
/**
* Input name
*/
name?: string;
/**
* Slider label
*/
label?: string;
/**
* Minimum value
*/
set min(min: number) {
if (!Utils.isUndefinedOrNull(min)) {
this._min = min;
this.updateInputCssPropWithValue(this._currentValue);
}
}
get min(): number {
return this._min;
}
/**
* Maximum value
*/
set max(max: number) {
if (!Utils.isUndefinedOrNull(max)) {
this._max = max;
this.updateInputCssPropWithValue(this._currentValue);
}
}
get max(): number {
return this._max;
}
/**
* Input value
*/
set value(val: number) {
if (!Utils.isUndefinedOrNull(val)) {
this._initialValue = val;
} else {
this._initialValue = this._min;
}
this._currentValue = this._initialValue;
this.inputValue$.next(this._currentValue);
this.cdr.markForCheck();
}
get value(): number {
return this._initialValue;
}
/**
* Slider input step
*/
step: number = 0.1;
/**
* Whether input is disabled or not
*/
isDisabled = false;
input: ElementRef;
ngAfterViewInit() {
this.inputValue$.pipe(takeUntil(this.unsubscribe)).subscribe((val) => {
this.updateInputCssPropWithValue(val);
});
}
ngOnDestroy() {
this.unsubscribe.next();
this.unsubscribe.complete();
}
/**
* Implemented as part of ControlValueAccessor.
* @ignore
*/
writeValue(value: number): void {
this.value = value;
}
/**
* Implemented as part of ControlValueAccessor.
* @ignore
*/
registerOnChange(fn: any): void {
this._onChange = fn;
}
/**
* Implemented as part of ControlValueAccessor.
* @ignore
*/
registerOnTouched(fn: any): void {
this._onTouched = fn;
}
/**
* Implemented as part of ControlValueAccessor.
* @ignore
*/
setDisabledState(isDisabled: boolean): void {
this.isDisabled = isDisabled;
this.cdr.markForCheck();
}
/**
* @ignore
*/
updateValue(event: Event) {
// @ts-ignore
const newVal = event?.target?.value;
if (newVal !== this._currentValue) {
this._currentValue = newVal;
this.writeValue(newVal);
this._onChange(newVal);
}
}
/**
* @ignore
*/
updateInputCssPropWithValue(value: number) {
if (!this.input?.nativeElement || Utils.isUndefinedOrNull(value)) {
return;
}
let percentage = (100 * (value - this.min)) / (this.max - this.min);
percentage = isNaN(percentage) ? 0 : percentage;
this.input.nativeElement.style.setProperty('--nj-slider-track-position', `${percentage}% 100%`);
}
}