/* eslint-disable @angular-eslint/directive-selector, @angular-eslint/no-host-metadata-property */ import { Directive, ElementRef, HostListener } from "@angular/core"; import { ControlValueAccessor, NG_VALUE_ACCESSOR } from "@angular/forms"; @Directive({}) export class ValueAccessor implements ControlValueAccessor { private onChange: (value: any) => void = () => {}; private onTouched: () => void = () => {}; protected lastValue: any; constructor(protected el: ElementRef) {} writeValue(value: any) { this.el.nativeElement.value = this.lastValue = value == null ? '' : value; } handleChangeEvent(value: any) { if (value !== this.lastValue) { this.lastValue = value; this.onChange(value); } } @HostListener('focusout') _handleBlurEvent() { this.onTouched(); } registerOnChange(fn: (value: any) => void) { this.onChange = fn; } registerOnTouched(fn: () => void) { this.onTouched = fn; } setDisabledState(disabled: boolean) { this.el.nativeElement.disabled = disabled; } } @Directive({ selector: 'duet-input:not([type=number]), duet-textarea, duet-date-picker', host: { '(duetChange)': 'handleChangeEvent($event.target.value)' }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: TextValueAccessorDirective, multi: true } ] }) export class TextValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: 'duet-range-slider, duet-select, duet-radio-group, duet-choice-group', host: { '(duetChange)': 'handleChangeEvent($event.target.value)' }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: SelectValueAccessorDirective, multi: true } ] }) export class SelectValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: 'duet-radio, duet-choice[type=radio]', host: { '(duetSelect)': 'handleChangeEvent($event.target.checked)' }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: RadioValueAccessorDirective, multi: true } ] }) export class RadioValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: 'duet-input[type=number], duet-number-input', host: { '(duetChange)': 'handleChangeEvent($event.target.value)' }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: NumericValueAccessorDirective, multi: true } ] }) export class NumericValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } registerOnChange(fn: (_: number | null) => void) { super.registerOnChange(value => { fn(value === '' ? null : parseFloat(value)); }); } } @Directive({ /* tslint:disable-next-line:directive-selector */ selector: 'duet-checkbox, duet-toggle, duet-choice[type=checkbox]', host: { '(duetChange)': 'handleChangeEvent($event.target.checked)' }, providers: [ { provide: NG_VALUE_ACCESSOR, useExisting: BooleanValueAccessorDirective, multi: true } ] }) export class BooleanValueAccessorDirective extends ValueAccessor { constructor(el: ElementRef) { super(el); } writeValue(value: any) { this.el.nativeElement.checked = this.lastValue = value == null ? false : value; } }