| /******************************************************************************** |
| * Copyright (c) 2020 Contributors to the Eclipse Foundation |
| * |
| * See the NOTICE file(s) distributed with this work for additional |
| * information regarding copyright ownership. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| ********************************************************************************/ |
| |
| import {ConnectedPosition} from "@angular/cdk/overlay"; |
| import {Component, EventEmitter, forwardRef, Input, Output, ViewChild} from "@angular/core"; |
| import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms"; |
| import {EKeyboardKeys} from "../../../util/events"; |
| import {DropDownDirective} from "../../drop-down"; |
| import {ISelectOption} from "../ISelectOption"; |
| |
| @Component({ |
| selector: "app-select", |
| templateUrl: "./select.component.html", |
| styleUrls: ["./select.component.scss"], |
| providers: [ |
| { |
| provide: NG_VALUE_ACCESSOR, |
| useExisting: forwardRef(() => SelectComponent), |
| multi: true |
| } |
| ] |
| }) |
| export class SelectComponent implements ControlValueAccessor { |
| |
| private static id = 0; |
| |
| @Input() |
| public appId = `CalendarControlComponent${SelectComponent.id++}`; |
| |
| @Input() |
| public appPlaceholder = ""; |
| |
| @Input() |
| public appValue: any; |
| |
| @Input() |
| public appOptions: ISelectOption[] = []; |
| |
| @Output() |
| public appValueChange = new EventEmitter<any>(); |
| |
| @ViewChild(DropDownDirective) |
| public dropDown: DropDownDirective; |
| |
| public readonly connectedPositions: ConnectedPosition[] = [ |
| { |
| originX: "start", |
| originY: "bottom", |
| overlayX: "start", |
| overlayY: "top", |
| offsetX: 4, |
| panelClass: "bottom" |
| }, |
| { |
| originX: "start", |
| originY: "top", |
| overlayX: "start", |
| overlayY: "bottom", |
| offsetX: 4, |
| panelClass: "top" |
| }, |
| { |
| originX: "start", |
| originY: "center", |
| overlayX: "start", |
| overlayY: "center", |
| panelClass: "center", |
| offsetX: 4 |
| } |
| ]; |
| |
| @Input() |
| public appDisabled = false; |
| |
| public onChange = (_: any) => null; |
| |
| public onTouch = () => null; |
| |
| public writeValue(obj: any, emit?: boolean) { |
| const oldValue = this.appValue; |
| this.appValue = obj; |
| if (emit && oldValue !== obj) { |
| this.appValueChange.emit(obj); |
| this.onChange(obj); |
| this.onTouch(); |
| } |
| } |
| |
| public registerOnChange(fn: any) { |
| this.onChange = typeof fn === "function" ? fn : this.onChange; |
| } |
| |
| public registerOnTouched(fn: any) { |
| this.onTouch = typeof fn === "function" ? fn : this.onTouch; |
| } |
| |
| public setDisabledState(isDisabled: boolean) { |
| this.appDisabled = isDisabled; |
| } |
| |
| public toggle(openOrClose?: boolean) { |
| this.dropDown.toggle(openOrClose); |
| } |
| |
| public onClickOnOption(value: any) { |
| this.toggle(false); |
| if (this.appDisabled) { |
| return; |
| } |
| this.writeValue(value, true); |
| } |
| |
| public onKeyDown(event: KeyboardEvent) { |
| switch (event?.key) { |
| case EKeyboardKeys.ESCAPE: |
| case EKeyboardKeys.TAB: |
| return this.toggle(false); |
| case EKeyboardKeys.ARROW_DOWN: |
| case EKeyboardKeys.ARROW_RIGHT: { |
| const value = this.getNextValue(); |
| if (this.appDisabled || value == null) { |
| return; |
| } |
| event.preventDefault(); |
| return this.writeValue(value, true); |
| } |
| case EKeyboardKeys.ARROW_UP: |
| case EKeyboardKeys.ARROW_LEFT: { |
| const value = this.getPreviousValue(); |
| if (this.appDisabled || value == null) { |
| return; |
| } |
| event.preventDefault(); |
| return this.writeValue(value, true); |
| } |
| } |
| } |
| |
| public getNextValue() { |
| if (!Array.isArray(this.appOptions)) { |
| return; |
| } |
| |
| if (this.appValue == null) { |
| return this.appOptions[0]?.value; |
| } else { |
| const index = this.appOptions.findIndex((o) => o?.value === this.appValue) + 1; |
| return this.appOptions[index < this.appOptions?.length ? index : 0]?.value; |
| } |
| } |
| |
| public getPreviousValue() { |
| if (!Array.isArray(this.appOptions)) { |
| return; |
| } |
| |
| if (this.appValue == null) { |
| return this.appOptions[this.appOptions.length - 1]?.value; |
| } else { |
| const index = this.appOptions.findIndex((o) => o?.value === this.appValue) - 1; |
| return this.appOptions[index > -1 ? index : this.appOptions.length - 1]?.value; |
| } |
| } |
| |
| } |