blumjs
Version:
A UI Package for Angular2
242 lines (207 loc) • 8.03 kB
text/typescript
import {
Component, Input, Output, EventEmitter, ContentChildren, QueryList, AfterContentInit,
HostListener, ElementRef
} from "@angular/core";
import {OptionComponent} from "./option.component";
export class SelectComponent implements AfterContentInit {
model: any;
searchable: boolean = true;
searchTerm: string = "";
disabled: boolean = false;
hidden: boolean = false;
multiple: boolean = false;
noResultMsg: string = "نتیجهای یافت نشد.";
modelChange: EventEmitter<any> = new EventEmitter<any>();
change: EventEmitter<any> = new EventEmitter<any>();
searchTermChange: EventEmitter<string> = new EventEmitter<string>();
private rtl: boolean = true;
private isOpen: boolean = false;
private selectedOptions: OptionComponent[] = [];
private noResult: boolean = false;
private tempOptions: {option: OptionComponent, text: string}[] = [];
options: QueryList<OptionComponent>;
constructor(private elementRef: ElementRef){}
ngAfterContentInit(): void {
console.time("Select Init");
this.listenToOptionEvents();
this.options.forEach((option: OptionComponent) => {
this.tempOptions.push({text: option.getText(), option: option});
option = Object.assign({text: option.getText()}, option);
if (option.value == this.model)
this.selectedOptions.push(option);
});
console.timeEnd("Select Init");
}
private modelChanged(): void {
console.time("Model Changed");
this.model = this.selectedOptions[0].value;
this.searchTerm = '';
this.searchTermChanged();
this.modelChange.emit(this.model);
console.timeEnd("Model Changed");
}
private searchTermChanged(): void {
console.time("Searching");
if (this.searchTerm === '') {
this.options.forEach((option) => {
option.hidden = false;
});
this.noResult = false;
return;
}
this.noResult = true;
this.tempOptions.forEach((tempOption) => {
tempOption.option.hidden = tempOption.text.toLowerCase().indexOf(this.searchTerm.toLowerCase()) <= -1;
if (!tempOption.option.hidden)
this.noResult = false;
});
this.searchTermChange.emit(this.searchTerm);
console.timeEnd("Searching");
}
private changed(): void {
this.change.emit(this.model);
}
private toggle(): void {
this.isOpen ? this.close() : this.open();
}
private open(): void {
console.time("Opening");
if (this.disabled)
return;
this.isOpen = true;
console.timeEnd("Opening");
}
private close(): void {
this.searchTerm = "";
this.isOpen = false;
}
private listenToOptionEvents(): void {
this.options.forEach((option: OptionComponent) => {
const sub = option.onSelect.subscribe(
(event) => {
console.time("Option Clicked");
if (this.multiple) {
let found: boolean = false;
for (let i = 0; i < this.selectedOptions.length; i++) {
if (this.selectedOptions[i] == Object.assign({text: event.getText()}, event)) {
this.selectedOptions[i] = Object.assign({text: event.getText()}, event);
found = true;
}
}
if (!found)
this.selectedOptions.push(Object.assign({text: event.getText()}, event));
} else {
this.selectedOptions[0] = Object.assign({text: event.getText()}, event);
}
console.timeEnd("Option Clicked");
this.modelChanged();
this.changed();
this.close();
}
)
})
}
public onClick(event: MouseEvent, targetElement: HTMLElement): void {
if (!targetElement) {
return;
}
if (!this.elementRef.nativeElement.contains(targetElement)) {
this.close();
}
};
}