import { ChangeDetectorRef, Component, Input, Output, EventEmitter, HostListener, forwardRef, Inject, Optional, ChangeDetectionStrategy, Injector, OnInit, ElementRef, ViewChild, OnDestroy } from '@angular/core'; import { NG_VALUE_ACCESSOR, ControlValueAccessor, NgControl } from '@angular/forms'; import { SWITCH_OPTIONS } from './switch.token'; import { SwitchModuleConfig } from './switch.config'; import { Observable, Subscription } from 'rxjs'; const UI_SWITCH_CONTROL_VALUE_ACCESSOR: any = { provide: NG_VALUE_ACCESSOR, /* tslint:disable-next-line: no-use-before-declare */ useExisting: forwardRef(() => SwitchComponent), multi: true }; @Component({ // tslint:disable-next-line: component-selector selector: 'farris-switch', template: ` {{ this.checkedLabel }} {{ this.uncheckedLabel }} `, providers: [UI_SWITCH_CONTROL_VALUE_ACCESSOR] }) export class SwitchComponent implements ControlValueAccessor, OnDestroy { private _beforeChange: Subscription; @Input() square: boolean; @Input() size: string | 'small'| 'medium' | 'large' = 'medium'; @Input() color: string; @Input() switchOffColor: string; @Input() switchColor: string; @Input() defaultBgColor: string; @Input() defaultBoColor: string; @Input() checkedLabel: string; @Input() uncheckedLabel: string; @Input() checked: boolean; @Input() readonly: boolean; @Input() disabled: boolean; @Input() editable = true; @Input() reverse: boolean; @Input() trueValue: any = true; @Input() falseValue: any = false; @Input() beforeChange: Observable; /** * @deprecated */ @Output() changeEvent = new EventEmitter(); @Output() clickHandle = new EventEmitter(); /** * Emits changed value */ @Output() valueChange = new EventEmitter(); @ViewChild('container') switchElRef: ElementRef; constructor( @Inject(SWITCH_OPTIONS) @Optional() public config: SwitchModuleConfig = {}, private cdr: ChangeDetectorRef, public injector: Injector ) { this.square = (config && config.square) || false; this.size = (config && config.size) || this.size; this.color = config && config.color; this.switchOffColor = config && config.switchOffColor; this.switchColor = config && config.switchColor; this.defaultBgColor = config && config.defaultBgColor; this.defaultBoColor = config && config.defaultBoColor; this.checkedLabel = config && config.checkedLabel; this.uncheckedLabel = config && config.uncheckedLabel; } ngOnDestroy() { if (this._beforeChange) { this._beforeChange.unsubscribe(); } } getColor(flag = '') { if (flag === 'borderColor') { return this.defaultBoColor; } if (flag === 'switchColor') { if (this.reverse) { return !this.checked ? this.switchColor : this.switchOffColor || this.switchColor; } return this.checked ? this.switchColor : this.switchOffColor || this.switchColor; } if (this.reverse) { return !this.checked ? this.color : this.defaultBgColor; } return this.checked ? this.color : this.defaultBgColor; } private updateChecked(event: any, isClick = true) { if (this.disabled || !this.editable) { return; } this.checked = !this.checked; const val = this.getValue(this.checked); // Component events this.valueChange.emit(val); this.changeEvent.emit(event); if (isClick) { this.clickHandle.emit({ event, checked: this.checked, value: val, instance: this }); } this.onChangeCallback(val); this.onTouchedCallback(val); this.cdr.detectChanges(); } @HostListener('click', ['$event']) onToggle(event: MouseEvent) { if (this.beforeChange) { this._beforeChange = this.beforeChange.subscribe((confirm: boolean) => { if (confirm) { this.updateChecked(event); } }); } else { this.updateChecked(event); } } @HostListener('keydown.Space', ['$event']) onSpaceHandle($event: any) { $event.preventDefault(); $event.stopPropagation(); this.updateChecked($event, false); } private getValue(checked: boolean) { if (this.trueValue !== undefined && this.falseValue !== undefined) { return checked ? this.trueValue : this.falseValue; } return checked; } writeValue(obj: any): void { if (this.trueValue !== undefined && this.falseValue !== undefined) { this.checked = obj == this.trueValue; } else { if (obj !== this.checked) { this.checked = !!obj; } } if (this.cdr && !this.cdr['destroyed']) { this.cdr.detectChanges(); } } registerOnChange(fn: any) { this.onChangeCallback = fn; } registerOnTouched(fn: any) { this.onTouchedCallback = fn; } setDisabledState(isDisabled: boolean) { this.disabled = isDisabled; } private onTouchedCallback = (v: any) => { }; private onChangeCallback = (v: any) => { }; }