Skip to content

Instantly share code, notes, and snippets.

@kilgarenone
Created May 22, 2017 07:25
Show Gist options
  • Save kilgarenone/d1912e9d2506d9a0a40fc0cfc58ad84f to your computer and use it in GitHub Desktop.
Save kilgarenone/d1912e9d2506d9a0a40fc0cfc58ad84f to your computer and use it in GitHub Desktop.
<md-select> with key search for specific option
<md-select [formControl]="selectFormControl"
(click)="detectKeys()"
[required]="isRequired"
[disabled]="isDisabled"
[attr.role]="'listbox'"
[attr.aria-labelledby]="placeholder"
placeholder="placeholder">
<md-option #selectBox *ngFor="let option of options"
[class.inFocus]="searchedOptionValue == option.value"
[value]="option.value">{{option.description}}
</md-option>
<input #getInput class="md-select-keySearch" value="">
</md-select>
import {
AfterViewInit,
Component,
ElementRef,
Input,
OnDestroy,
OnInit,
QueryList,
Renderer,
ViewChild,
ViewChildren,
} from '@angular/core';
import { FormControl } from '@angular/forms';
import 'rxjs/add/operator/debounceTime';
import 'rxjs/add/operator/distinctUntilChanged';
import 'rxjs/add/operator/switchMap';
import 'rxjs/add/operator/takeUntil';
import { Observable } from 'rxjs/Observable';
import 'rxjs/observable/fromEvent';
import { Subscription } from 'rxjs/Subscription';
@Component({
selector: 'app-ui-select',
templateUrl: './ui-select.component.html',
styleUrls: ['./ui-select.component.scss'],
})
export class UiSelectComponent implements OnInit, OnDestroy, AfterViewInit {
@Input() options: Object[];
@Input() placeholder: string;
@Input() isRequired: string;
@Input() isDisabled: string;
@ViewChildren('selectBox') selects: QueryList<any>;
@ViewChild('getInput') optionSearch: ElementRef;
// Get previously selected value in order to mark as 'selected' in its option element in the template
// currentSelectionValue: number = 111;
optionsCache: ElementRef[] = [];
keySelectSubscription: Subscription;
selectFormControl: FormControl = new FormControl('');
searchedOptionValue: number;
constructor(private renderer: Renderer) { }
/**
* The value of the selected option in a Select element. Do something to the value here.
*/
getSelectOption(value: number): void {
console.log('ahhh', value);
}
detectKeys() {
setTimeout(() => {
this.renderer.invokeElementMethod(this.optionSearch.nativeElement, 'focus', []);
this.subscribeToKeys();
}, 500);
}
subscribeToKeys() {
const keyUpStream: Observable<any> = Observable.fromEvent(this.optionSearch.nativeElement, 'keyup');
const enterKeyIsPressedStream = Observable.fromEvent(this.optionSearch.nativeElement, 'keyup')
.filter((e: KeyboardEvent) => e.keyCode === 13);
const mergedKeyStreamOnErr = (e) => { };
const mergedKeyStreamOnComplete = () => { this.selectFormControl.setValue(this.searchedOptionValue); };
const mergedKeyStream = keyUpStream.takeUntil(enterKeyIsPressedStream);
this.keySelectSubscription = mergedKeyStream.map((e) => e.target.value)
.filter((keyword) => keyword.length > 1)
.debounceTime(200) // wait 100ms before emitting last event
.distinctUntilChanged() // only emit if value is different from previous value
.do((termDebug) => console.log(termDebug))
.switchMap(this.lookUpOptions.bind(this))
.subscribe(this.focusSearchedOption.bind(this),
mergedKeyStreamOnErr,
mergedKeyStreamOnComplete.bind(this));
}
focusSearchedOption(matchedOption) {
const focusThisOption = this.optionsCache.find((option: any) => option.value === matchedOption.value);
const optionEl = focusThisOption['_element'].nativeElement;
optionEl.offsetParent.scrollTop = optionEl.offsetTop;
this.searchedOptionValue = focusThisOption['value'];
this.optionSearch.nativeElement.value = '';
}
lookUpOptions(keyWord): any {
const firstFoundOption: any = this.options.find((option) => {
let desc = option['description'].toLowerCase();
return desc.substring(0, keyWord.length) === keyWord || desc.indexOf(keyWord) > -1;
});
let arr = [];
arr.push(firstFoundOption);
console.log(arr);
return arr;
}
ngAfterViewInit() {
this.selects.changes.subscribe((option: QueryList<any>) => { this.optionsCache = option.toArray(); });
}
ngOnInit() {
this.selectFormControl.valueChanges.subscribe((val) => console.log(val));
}
ngOnDestroy() {
// prevent memory leak when component destroyed
this.keySelectSubscription.unsubscribe();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment