pm-controls
Version:
ProModel Controls
312 lines (266 loc) • 9.47 kB
text/typescript
import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
EventEmitter,
Input,
OnInit,
OnDestroy,
Output,
SimpleChanges,
TemplateRef,
ViewContainerRef,
ViewChild
} from '@angular/core';
import { CompatibilityService } from '../../../services/compatibility/compatibility-service';
import { SelectionMode } from '../../../../objects/enums/selection-mode';
import { TextBoxComponent } from '../text-box/text-box-component';
import { VirtualPanelComponent } from '../../panels/virtual-panel/virtual-panel-component';
import { StringExtensions } from '../../../../objects/extensions/string-extensions';
import { KeyCodes } from '../../../../objects/key-codes';
import { ArrayExtensions } from '../../../../objects/extensions/array-extensions';
export class ComboBoxComponent implements OnInit, OnDestroy {
constructor(
public changeDetectorRef: ChangeDetectorRef,
public viewContainerRef: ViewContainerRef,
public CompatibilityService: CompatibilityService) {
if(this.CompatibilityService.IsLegacyBrowser)
this.DropDownWidth = "";
this.changeDetectorRef.detach();
this.el = viewContainerRef.element.nativeElement;
this.clickEvent = this.HandleClick.bind(this);
}
Label;
ComboBoxItemClass: string = "combo-box-item";
ComboBoxPanelClass: string = "combo-box-panel-default";
ComboBoxButtonClass: string = "button-icon-default";
ItemHeight: number = 30;
Watermark: string;
Width: string;
IsBusy: boolean;
IsDisabled: boolean;
IsReadOnly: boolean;
ShowRemoveItem: boolean = true;
IsDropDownOpen: boolean;
IsDropDownOpenChange: EventEmitter<boolean> = new EventEmitter();
SelectionMode: SelectionMode = SelectionMode.Single;
ShowClearButton: boolean = true;
ItemsSource: Array<any>;
SelectedItems: Array<any> = [];
DisplayMemberPath: any; // should be property name or function.
SelectedItemsChange: EventEmitter<any> = new EventEmitter<any>();
SelectedItemChange: EventEmitter<any> = new EventEmitter<any>();
TextChange: EventEmitter<string> = new EventEmitter<string>();
textBox: TextBoxComponent;
ItemTemplate: TemplateRef<any>;
ComboBoxListItemSelectedClass: string = "combo-box-list-item-selected";
ShowHighlight: boolean = true;
HighlightedItem: any;
virtualPanel: VirtualPanelComponent;
DropDownWidth : string = "100%";
public filteredItemSource: any;
private el: Element;
private clickEvent;
ngOnInit() {
this.IsDropDownOpen = this.IsDropDownOpen || false;
this.IsDropDownOpenChange.emit(this.IsDropDownOpen);
this.filterItemSource();
let body = document.querySelector('body');
body.addEventListener('click', this.clickEvent, false);
}
private text: any;
get Text(): any {
return this.text;
}
set Text(value: any) {
if (this.text != value){
this.text = value;
this.TextChange.emit(this.text);
this.changeDetectorRef.detectChanges();
}
}
private selectedItem: any;
get SelectedItem(): any {
return this.selectedItem;
}
set SelectedItem(value: any) {
this.selectedItem = value;
if (this.SelectionMode == SelectionMode.Single)
this.SelectedItems.length = 0;
if (this.selectedItem && this.SelectedItems.indexOf(this.selectedItem) == -1)
this.SelectedItems.push(this.selectedItem);
if (this.SelectionMode == SelectionMode.Single)
this.IsDropDownOpen = false;
else
this.SelectedItemsChange.emit(this.SelectedItems);
this.Text = "";
this.TextChange.emit(this.Text);
this.filterItemSource();
this.SelectedItemChange.emit(this.SelectedItem);
}
SelectItem(item: any) {
if (!this.SelectedItems) this.SelectedItems = [];
if (this.SelectedItems.indexOf(item) == -1)
this.SelectedItem = item;
else {
this.RemoveSelectedItem(item);
}
this.changeDetectorRef.detectChanges();
}
ngOnDestroy() {
let body = document.querySelector('body');
body.removeEventListener('click', this.clickEvent, false);
}
HandleClick(e) {
if (!this.IsDropDownOpen || !e.target) { return; };
if (this.el !== e.target && !this.el.contains((<any>e.target))) {
this.IsDropDownOpen = false;
this.IsDropDownOpenChange.emit(this.IsDropDownOpen);
this.virtualPanel.ResetScroll();
this.changeDetectorRef.detectChanges();
}
}
get AllSelected(): boolean {
if (this.SelectedItems && this.ItemsSource && this.ItemsSource.length > 1)
return this.ItemsSource.every(r => this.SelectedItems.includes(r));
return false;
}
highlight() {
if (this.filteredItemSource && this.filteredItemSource.length > 0)
{
this.HighlightedItem = this.filteredItemSource[0];
}
}
filterItemSource() {
if(this.Text) {
var lowerCaseText = this.Text.toLowerCase();
this.filteredItemSource = this.ItemsSource.filter(item => this.getItemDisplay(item).toLowerCase().indexOf(lowerCaseText)!=-1);
}
else {
this.filteredItemSource = this.ItemsSource;
}
this.highlight();
this.changeDetectorRef.detectChanges();
}
OnClickClear() {
this.IsDropDownOpen = false;
this.Clear();
}
Clear() {
this.SelectedItems.length = 0;
this.SelectedItem = undefined;
this.changeDetectorRef.detectChanges();
}
SelectAll() {
this.SelectedItems = this.ItemsSource.slice();
this.SelectedItemsChange.emit(this.SelectedItems);
this.changeDetectorRef.detectChanges();
}
get WatermarkDisplay() {
if (this.SelectedItem || (this.SelectedItems && this.SelectedItems.length > 0))
return;
return this.Watermark;
}
RemoveSelectedItem(item:any) {
var idx = this.SelectedItems.indexOf(item);
if(idx<0) {
console.error("Could not find selected item to remove.");
console.trace();
return;
}
this.SelectedItems.splice(idx,1);
if (this.SelectedItem == item) {
this.SelectedItem = undefined;
} else {
this.SelectedItemsChange.emit(this.SelectedItems);
}
this.textBox.Focus();
}
RemoveAllItem() {
this.Clear();
}
onDropDownClick(event) {
this.IsDropDownOpen = !this.IsDropDownOpen;
this.IsDropDownOpenChange.emit(this.IsDropDownOpen);
if (this.IsDropDownOpen)
this.textBox.Focus();
this.changeDetectorRef.detectChanges();
}
onFocusChange(event) {
this.IsDropDownOpen = true;
this.IsDropDownOpenChange.emit(this.IsDropDownOpen);
this.filterItemSource();
}
onTextChange(value) {
this.Text = value;
this.TextChange.emit(this.Text);
this.filterItemSource();
if (StringExtensions.isNullOrEmpty(this.Text) == false) {
this.IsDropDownOpen = true;
}
}
onKeyDown(event) {
if (event.keyCode == KeyCodes.DOWN)
{
var item = ArrayExtensions.findNextItem(this.filteredItemSource, this.HighlightedItem);
if (item) {
this.HighlightedItem = item;
this.virtualPanel.ScrollToItem(item);
this.changeDetectorRef.detectChanges();
}
}
if (event.keyCode == KeyCodes.UP)
{
var item = ArrayExtensions.findPreviousItem(this.filteredItemSource, this.HighlightedItem);
if (item) {
this.HighlightedItem = item;
this.virtualPanel.ScrollToItem(item);
this.changeDetectorRef.detectChanges();
}
}
if (event.keyCode == KeyCodes.BACKSPACE)
{
if (StringExtensions.isNullOrEmpty(this.Text)) {
if(this.SelectedItems.length>0)
this.RemoveSelectedItem(this.SelectedItems[this.SelectedItems.length-1]);
}
if (this.SelectionMode == SelectionMode.Single)
this.IsDropDownOpen = true;
}
}
getItemDisplay(item) :string {
if (!item)
return;
if (!this.DisplayMemberPath)
return item;
if(typeof this.DisplayMemberPath === "function")
return this.DisplayMemberPath(item);
else if (item[this.DisplayMemberPath])
return <string>item[this.DisplayMemberPath];
return item;
}
onKeyUp(event) {
if (event.keyCode == KeyCodes.ESCAPE) {
this.IsDropDownOpen = false;
this.IsDropDownOpenChange.emit(this.IsDropDownOpen);
this.virtualPanel.ResetScroll();
this.changeDetectorRef.detectChanges();
}
if (event.keyCode == KeyCodes.ENTER)
this.SelectedItem = this.HighlightedItem;
}
get ComboBoxModeClass() {
return this.SelectionMode == SelectionMode.Single ? "combo-box-panel-single" : "combo-box-panel-multiple";
}
RaiseChange() {
this.changeDetectorRef.detectChanges();
}
}