mirror of https://github.com/Squidex/squidex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
149 lines
3.7 KiB
149 lines
3.7 KiB
/*
|
|
* Squidex Headless CMS
|
|
*
|
|
* @license
|
|
* Copyright (c) Squidex UG (haftungsbeschränkt). All rights reserved.
|
|
*/
|
|
|
|
import { AfterContentInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, forwardRef, Input, QueryList, TemplateRef } from '@angular/core';
|
|
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
|
|
|
|
const KEY_ENTER = 13;
|
|
const KEY_ESCAPE = 27;
|
|
const KEY_UP = 38;
|
|
const KEY_DOWN = 40;
|
|
|
|
import { ModalModel } from '@app/framework/internal';
|
|
|
|
export const SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR: any = {
|
|
provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => DropdownComponent), multi: true
|
|
};
|
|
|
|
@Component({
|
|
selector: 'sqx-dropdown',
|
|
styleUrls: ['./dropdown.component.scss'],
|
|
templateUrl: './dropdown.component.html',
|
|
providers: [SQX_DROPDOWN_CONTROL_VALUE_ACCESSOR],
|
|
changeDetection: ChangeDetectionStrategy.OnPush
|
|
})
|
|
export class DropdownComponent implements AfterContentInit, ControlValueAccessor {
|
|
private callChange = (v: any) => { /* NOOP */ };
|
|
private callTouched = () => { /* NOOP */ };
|
|
|
|
@Input()
|
|
public items: any[] = [];
|
|
|
|
@ContentChildren(TemplateRef)
|
|
public templates: QueryList<any>;
|
|
|
|
public dropdown = new ModalModel();
|
|
|
|
public selectedItem: any;
|
|
public selectedIndex = -1;
|
|
public selectionTemplate: TemplateRef<any>;
|
|
|
|
public itemTemplate: TemplateRef<any>;
|
|
|
|
public isDisabled = false;
|
|
|
|
constructor(
|
|
private readonly changeDetector: ChangeDetectorRef
|
|
) {
|
|
}
|
|
|
|
public ngAfterContentInit() {
|
|
if (this.templates.length === 1) {
|
|
this.itemTemplate = this.selectionTemplate = this.templates.first;
|
|
} else {
|
|
this.templates.forEach(template => {
|
|
if (template.name === 'selection') {
|
|
this.selectionTemplate = template;
|
|
} else {
|
|
this.itemTemplate = template;
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
public writeValue(obj: any) {
|
|
this.selectIndex(this.items && obj ? this.items.indexOf(obj) : 0);
|
|
|
|
this.changeDetector.markForCheck();
|
|
}
|
|
|
|
public setDisabledState(isDisabled: boolean): void {
|
|
this.isDisabled = isDisabled;
|
|
|
|
this.changeDetector.markForCheck();
|
|
}
|
|
|
|
public registerOnChange(fn: any) {
|
|
this.callChange = fn;
|
|
}
|
|
|
|
public registerOnTouched(fn: any) {
|
|
this.callTouched = fn;
|
|
}
|
|
|
|
public onKeyDown(event: KeyboardEvent) {
|
|
switch (event.keyCode) {
|
|
case KEY_UP:
|
|
this.up();
|
|
return false;
|
|
case KEY_DOWN:
|
|
this.down();
|
|
return false;
|
|
case KEY_ESCAPE:
|
|
case KEY_ENTER:
|
|
if (this.dropdown.isOpen) {
|
|
this.close();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
public open() {
|
|
this.dropdown.show();
|
|
this.callTouched();
|
|
}
|
|
|
|
public selectIndexAndClose(selectedIndex: number) {
|
|
this.selectIndex(selectedIndex);
|
|
this.close();
|
|
}
|
|
|
|
private close() {
|
|
this.dropdown.hide();
|
|
}
|
|
|
|
private up() {
|
|
this.selectIndex(this.selectedIndex - 1);
|
|
}
|
|
|
|
private down() {
|
|
this.selectIndex(this.selectedIndex + 1);
|
|
}
|
|
|
|
private selectIndex(selectedIndex: number) {
|
|
if (selectedIndex < 0) {
|
|
selectedIndex = 0;
|
|
}
|
|
|
|
const items = this.items || [];
|
|
|
|
if (selectedIndex >= items.length) {
|
|
selectedIndex = items.length - 1;
|
|
}
|
|
|
|
const value = items[selectedIndex];
|
|
|
|
if (value !== this.selectedItem) {
|
|
this.selectedIndex = selectedIndex;
|
|
this.selectedItem = value;
|
|
|
|
this.callChange(value);
|
|
}
|
|
}
|
|
}
|