Skip to content

Commit

Permalink
test(igx-autocomplete): auto highlight first item #3585
Browse files Browse the repository at this point in the history
  • Loading branch information
Lipata committed Jan 23, 2019
1 parent 6ec055f commit 6ae8c2a
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,15 @@ export class IgxComboDropDownComponent extends IgxDropDownComponent implements I
this.items.length - 1;
}

@ContentChildren(IgxComboItemComponent, { descendants: true })
protected children: QueryList<IgxDropDownItemBase> = null;

private _scrollPosition = 0;

/**
* @hidden
* @internal
*/
@ContentChildren(IgxComboItemComponent, { descendants: true })
public children: QueryList<IgxDropDownItemBase> = null;

/**
* @hidden
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { IgxInputGroupModule } from '../../input-group';
import { IgxDropDownModule, IgxDropDownComponent } from '../../drop-down';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

fdescribe('IgxAutocomplete', () => {
describe('IgxAutocomplete', () => {
let fixture;
let autocomplete: IgxAutocompleteDirective;
let input: IgxInputDirective;
Expand Down Expand Up @@ -69,17 +69,43 @@ fdescribe('IgxAutocomplete', () => {
expect(dropDown.collapsed).toBeTruthy();
}));

it('Auto-highlighting first item', fakeAsync(() => {
it('Auto-highlight first item', fakeAsync(() => {
UIInteractions.sendInput(input, 's', fixture);
fixture.detectChanges();
tick();
expect(dropDown.children.first.focused).toBeTruthy();
expect(dropDown.items[0].focused).toBeTruthy();
expect(dropDown.items[0].value).toBe('Sofia');

UIInteractions.triggerKeyDownEvtUponElem('enter', input.nativeElement, true);
fixture.detectChanges();
tick();
expect(fixture.componentInstance.townSelected).toBe('Sofia');

UIInteractions.sendInput(input, 'st', fixture);
fixture.detectChanges();
tick();
expect(dropDown.children.first.focused).toBeTruthy();
expect(dropDown.items[0].focused).toBeTruthy();
expect(dropDown.items[0].value).toBe('Stara Zagora');

UIInteractions.sendInput(input, 's', fixture);
fixture.detectChanges();
tick();
expect(dropDown.children.first.focused).toBeTruthy();
expect(dropDown.items[0].focused).toBeTruthy();
expect(dropDown.items[0].value).toBe('Sofia');
expect(dropDown.items[1].focused).toBeFalsy();
expect(dropDown.items[1].value).toBe('Stara Zagora');
}));

it('Disabled', fakeAsync(() => {}));
it('Selection and events', fakeAsync(() => {}));
it('Keyboard Navigation', fakeAsync(() => {}));
it('DropDown settings', fakeAsync(() => {}));
it('DropDown default width', fakeAsync(() => {}));
it('Aria', fakeAsync(() => {}));
it('ReactiveForm', fakeAsync(() => {}));
});
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
//#region imports
import {
Directive, Input, Self, Optional, Inject, HostBinding, Output, EventEmitter,
NgModule, ElementRef, HostListener } from '@angular/core';
NgModule, ElementRef, HostListener, ChangeDetectorRef } from '@angular/core';
import { NgModel, FormControlName } from '@angular/forms';
import { CommonModule } from '@angular/common';
import { first } from 'rxjs/operators';
import { first, takeUntil } from 'rxjs/operators';
import { CancelableEventArgs } from '../../core/utils';
import { OverlaySettings, AbsoluteScrollStrategy, ConnectedPositioningStrategy } from '../../services';
import { ISelectionEventArgs } from '../../drop-down';
import { IgxDropDownModule, IgxDropDownComponent } from '../../drop-down/drop-down.component';
import { IgxDropDownItemNavigationDirective } from '../../drop-down/drop-down-navigation.directive';
import { Subject } from 'rxjs';
//#endregion

/**
Expand All @@ -27,11 +28,13 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective

constructor(@Self() @Optional() @Inject(NgModel) protected ngModel: NgModel,
@Self() @Optional() @Inject(FormControlName) protected formControl: FormControlName,
protected elementRef: ElementRef) {
protected elementRef: ElementRef,
protected cdr: ChangeDetectorRef) {
super(null);
}

protected id: string;
protected queryListNotifier$ = new Subject<boolean>();
protected get model() {
return this.ngModel ? this.ngModel : this.formControl;
}
Expand All @@ -41,7 +44,7 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
}

private get collapsed(): boolean {
return this.target ? this.target.collapsed : true;
return this.dropDown ? this.dropDown.collapsed : true;
}

@Input('igxAutocomplete')
Expand Down Expand Up @@ -106,7 +109,7 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
if (this.collapsed) {
this.open();
} else {
this.highlightFirstItem();
this.unhighlightFirstItem();
}
}
@HostListener('blur', ['$event'])
Expand All @@ -123,6 +126,7 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective

private close() {
this.dropDown.close();
this.queryListNotifier$.complete();
}

private open() {
Expand All @@ -133,13 +137,14 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
this.dropDown.onOpened.pipe(first()).subscribe(() => {
this.highlightFirstItem();
});
this.dropDown.children.changes.pipe(takeUntil(this.queryListNotifier$)).subscribe(() => this.highlightFirstItem());
}

private select = (value: ISelectionEventArgs) => { // ?
if (!value.newSelection) {
return;
}
value.cancel = true;
value.cancel = true; // Disable selection in the drop down, because in auto complete we do not save selection.
const newValue = value.newSelection.value;
const args: IAutocompleteItemSelectionEventArgs = { value: newValue, cancel: false };
this.onItemSelected.emit(args);
Expand All @@ -150,12 +155,20 @@ export class IgxAutocompleteDirective extends IgxDropDownItemNavigationDirective
this.close();
}

private unhighlightFirstItem() {
const firstItem = this.dropDown.items[0];
if (firstItem) {
firstItem.isFocused = false;
}
}

private highlightFirstItem() {
const firstMatch = this.target.items[0];
if (firstMatch) {
firstMatch.isFocused = true;
this.target.focusedItem = firstMatch;
const firstItem = this.dropDown.items[0];
if (firstItem) {
firstItem.isFocused = true;
this.dropDown.focusedItem = firstItem;
}
this.cdr.detectChanges();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export abstract class IgxDropDownBase implements IDropDownList {
protected _height;
protected _focusedItem: any = null;
protected _id = `igx-drop-down-${NEXT_ID++}`;
protected children: QueryList<IgxDropDownItemBase>;

/**
* Get dropdown's html element of it scroll container
Expand All @@ -30,6 +29,12 @@ export abstract class IgxDropDownBase implements IDropDownList {
return this.element;
}

/**
* @hidden
* @internal
*/
public children: QueryList<IgxDropDownItemBase>;

/**
* Emitted when item selection is changing, before the selection completes
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,17 @@ import { OverlaySettings } from '../services';
providers: [{ provide: IGX_DROPDOWN_BASE, useExisting: IgxDropDownComponent }]
})
export class IgxDropDownComponent extends IgxDropDownBase implements IDropDownBase, OnInit, OnDestroy {
@ContentChildren(forwardRef(() => IgxDropDownItemComponent))
protected children: QueryList<IgxDropDownItemBase>;

@ViewChild(IgxToggleDirective)
protected toggleDirective: IgxToggleDirective;

protected destroy$ = new Subject<boolean>();
/**
* @hidden
* @internal
*/
@ContentChildren(forwardRef(() => IgxDropDownItemComponent))
public children: QueryList<IgxDropDownItemBase>;

/**
* Gets/sets whether items take focus. Disabled by default.
* When enabled, drop down items gain tab index and are focused when active -
Expand Down

0 comments on commit 6ae8c2a

Please sign in to comment.