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) => { };
}