diff --git a/ui/src/app/shared/autocomplete/autocomplete.component.html b/ui/src/app/shared/autocomplete/autocomplete.component.html
index e4b5addb6..977f346db 100644
--- a/ui/src/app/shared/autocomplete/autocomplete.component.html
+++ b/ui/src/app/shared/autocomplete/autocomplete.component.html
@@ -22,7 +22,7 @@
class="dropdown-item"
[class.active]="state.currentState.selected === i"
[class.focused]="state.currentState.focused === i"
- id="{{ id }}__option--{{ i }}"
+ [id]="this.getOptionId(i)"
(focusout)="handleOptionBlur($event, i)"
(click)="handleOptionClick(i)"
(mousedown)="handleOptionMouseDown($event)"
@@ -35,8 +35,15 @@
{{ noneFoundText }}
-
- {{ showMoreText }}
+
+ {{ showMoreText }}
diff --git a/ui/src/app/shared/autocomplete/autocomplete.component.spec.ts b/ui/src/app/shared/autocomplete/autocomplete.component.spec.ts
index a65503435..c7c75abf5 100644
--- a/ui/src/app/shared/autocomplete/autocomplete.component.spec.ts
+++ b/ui/src/app/shared/autocomplete/autocomplete.component.spec.ts
@@ -226,20 +226,23 @@ describe('AutoComplete Input Component', () => {
describe('handleEnter handler', () => {
const opts = ['foo', 'bar', 'baz'];
it('should call preventDefault on the provided event if the menu is currently open', () => {
- const ev = { preventDefault: jasmine.createSpy('preventDefault') };
+ const ev = { preventDefault: () => {} } as KeyboardEvent;
+ spyOn(ev, 'preventDefault');
instanceUnderTest.state.setState({ menuOpen: true});
instanceUnderTest.handleEnter(ev);
expect(ev.preventDefault).toHaveBeenCalled();
});
it('should NOT call preventDefault on the provided event if the menu is not open', () => {
- const ev = { preventDefault: jasmine.createSpy('preventDefault') };
+ const ev = { preventDefault: () => { } } as KeyboardEvent;
+ spyOn(ev, 'preventDefault');
instanceUnderTest.state.setState({ menuOpen: false });
instanceUnderTest.handleEnter(ev);
expect(ev.preventDefault).not.toHaveBeenCalled();
});
it('should call componentBlur if there is no selected option and the query is not in the options', () => {
- const ev = { preventDefault: jasmine.createSpy('preventDefault') };
+ const ev = { preventDefault: () => { } } as KeyboardEvent;
+ spyOn(ev, 'preventDefault');
spyOn(instanceUnderTest, 'handleComponentBlur');
instanceUnderTest.state.setState({ menuOpen: true, selected: -1 });
instanceUnderTest.handleEnter(ev);
@@ -253,7 +256,8 @@ describe('AutoComplete Input Component', () => {
it('should call handleOptionClick if there is no selected option but the query is in the options', () => {
const i = 0;
const val = opts[i];
- const ev = { preventDefault: jasmine.createSpy('preventDefault') };
+ const ev = { preventDefault: () => { } } as KeyboardEvent;
+ spyOn(ev, 'preventDefault');
testHostInstance.configure({ options: opts });
instanceUnderTest.input.setValue(val);
testHostFixture.detectChanges();
diff --git a/ui/src/app/shared/autocomplete/autocomplete.component.ts b/ui/src/app/shared/autocomplete/autocomplete.component.ts
index 340b02c64..86a2b4e33 100644
--- a/ui/src/app/shared/autocomplete/autocomplete.component.ts
+++ b/ui/src/app/shared/autocomplete/autocomplete.component.ts
@@ -151,7 +151,7 @@ export class AutoCompleteComponent implements OnInit, OnDestroy, OnChanges, Afte
});
}
- handleViewMore($event: MouseEvent): void {
+ handleViewMore($event: MouseEvent | KeyboardEvent | Event): void {
$event.preventDefault();
$event.stopPropagation();
this.handleInputBlur();
@@ -274,9 +274,12 @@ export class AutoCompleteComponent implements OnInit, OnDestroy, OnChanges, Afte
handleDownArrow(event: KeyboardEvent): void {
event.preventDefault();
- const isNotAtBottom = this.state.currentState.selected !== this.matches.length - 1;
+ let isNotAtBottom = this.state.currentState.selected !== this.matches.length - 1;
+ if (this.showMoreAvailable) {
+ isNotAtBottom = this.state.currentState.selected !== this.matches.length;
+ }
const allowMoveDown = isNotAtBottom && this.state.currentState.menuOpen;
- if (allowMoveDown || this.showMoreAvailable) {
+ if (allowMoveDown) {
this.handleOptionFocus(this.state.currentState.selected + 1);
}
}
@@ -289,7 +292,7 @@ export class AutoCompleteComponent implements OnInit, OnDestroy, OnChanges, Afte
}
}
- handleEnter(event: KeyboardEvent | { preventDefault: () => {} }): void {
+ handleEnter(event: KeyboardEvent): void {
let { selected, menuOpen } = this.state.currentState,
query = this.input.value;
if (menuOpen) {
@@ -300,8 +303,10 @@ export class AutoCompleteComponent implements OnInit, OnDestroy, OnChanges, Afte
hasSelectedOption = queryIndex > -1;
selected = hasSelectedOption ? queryIndex : selected;
}
- if (hasSelectedOption) {
+ if (hasSelectedOption && selected < this.matches.length) {
this.handleOptionClick(selected);
+ } else if (hasSelectedOption && selected === this.matches.length) {
+ this.handleViewMore(event as KeyboardEvent);
} else {
this.handleComponentBlur({
focused: -1,
@@ -333,15 +338,18 @@ export class AutoCompleteComponent implements OnInit, OnDestroy, OnChanges, Afte
return !!(agent.match(/(iPod|iPhone|iPad)/g) && agent.match(/AppleWebKit/g));
}
+ getOptionId(index): string {
+ return `${this.id}__option--${index}`;
+ }
+
get hasAutoselect(): boolean {
return this.isIosDevice() ? false : this.autoSelect;
}
get activeDescendant (): string {
- let state = this.state.currentState,
- focused = state.focused,
+ let { focused } = this.state.currentState,
optionFocused = focused !== -1 && focused !== null;
- return optionFocused ? `${ this.id }__option--${ focused }` : 'false';
+ return optionFocused ? this.getOptionId(focused) : null;
}
get displayState(): any {