[resultTemplate]="displayTemplate"
[inputFormatter]="formatDisplayString"
(click)="click$.next($event.target.value)"
+ (blur)="onBlur()"
(selectItem)="selectorChanged($event)"
- #input #instance="ngbTypeahead"/>
+ #instance="ngbTypeahead"/>
<div class="d-flex flex-column icons" (click)="openMe($event)">
<span class="material-icons">keyboard_arrow_up</span>
<span class="material-icons">keyboard_arrow_down</span>
export interface TypeaheadEntry {
id: any;
label: string;
- disabled?: boolean;
+ freetext?: boolean;
}
@Component({
selected: TypeaheadEntry;
click$: Subject<string>;
entrylist: TypeaheadEntry[];
+ freeTextId: number;
@ViewChild('instance') instance: NgbTypeahead;
// box regardless of any text that already exists there.
@Input() clickShowsAll = true;
+ @Input() allowFreeText = false;
+
// Entry ID of the default entry to select (optional)
// onChange() is NOT fired when applying the default value
@Input() startId: any;
this.entrylist = [];
this.click$ = new Subject<string>();
this.onChange = new EventEmitter<TypeaheadEntry>();
+ this.freeTextId = -1;
this.formatDisplayString = (result: TypeaheadEntry) => {
return result.label.trim();
setTimeout(() => this.click$.next(''));
}
+ onBlur() {
+
+ if (typeof this.selected === 'string' && this.selected !== '') {
+ // Free text entered which does not match a known entry
+
+ if (this.allowFreeText) {
+ // translate it into a dummy TypeaheadEntry
+ // and manually fire the onchange handler.
+ this.selected = {
+ id: this.freeTextId--,
+ label: this.selected,
+ freetext: true
+ }
+ this.selectorChanged(
+ {item: this.selected, preventDefault: () => true});
+ } else {
+ // If free text is now allowed, clear the value when
+ // the user navigates away to avoid confusion.
+ this.selected = null;
+ }
+ }
+ }
// Fired by the typeahead to inform us of a change.
- // TODO: this does not fire when the value is cleared :( -- implement
- // change detection on this.selected to look specifically for NULL.
+ // This only fires when an item in the list is selected, not when
+ // the value is cleared or free-text is used.
selectorChanged(selEvent: NgbTypeaheadSelectItemEvent) {
+ console.log('selector changed');
this.onChange.emit(selEvent.item.id);
}