diff --git a/components/auto-complete/demo/certain-category.ts b/components/auto-complete/demo/certain-category.ts index abd8e71e5d..bc8a622d11 100644 --- a/components/auto-complete/demo/certain-category.ts +++ b/components/auto-complete/demo/certain-category.ts @@ -1,4 +1,4 @@ -import { ChangeDetectionStrategy, Component, OnInit, ViewEncapsulation } from '@angular/core'; +import { Component, OnInit, ViewEncapsulation } from '@angular/core'; export interface AutocompleteOptionGroups { title: string; @@ -9,7 +9,6 @@ export interface AutocompleteOptionGroups { @Component({ selector: 'nz-demo-auto-complete-certain-category', encapsulation: ViewEncapsulation.None, - changeDetection: ChangeDetectionStrategy.OnPush, template: `
@@ -32,7 +31,7 @@ export interface AutocompleteOptionGroups { 更多 - + {{ option.title }} {{ option.count }} 人 关注 @@ -58,6 +57,8 @@ export class NzDemoAutoCompleteCertainCategoryComponent implements OnInit { inputValue: string; optionGroups: AutocompleteOptionGroups[]; + constructor() {} + onChange(value: string): void { console.log(value); } diff --git a/components/auto-complete/demo/non-case-sensitive.ts b/components/auto-complete/demo/non-case-sensitive.ts index 5297692399..79389a0cd3 100644 --- a/components/auto-complete/demo/non-case-sensitive.ts +++ b/components/auto-complete/demo/non-case-sensitive.ts @@ -9,10 +9,10 @@ import { Component, ViewEncapsulation } from '@angular/core'; placeholder="try to type \`b\`" nz-input [(ngModel)]="inputValue" - (input)="onInput($event.target?.value)" + (ngModelChange)="onChange($event)" [nzAutocomplete]="auto" /> - +
` }) @@ -25,7 +25,7 @@ export class NzDemoAutoCompleteNonCaseSensitiveComponent { this.filteredOptions = this.options; } - onInput(value: string): void { - this.filteredOptions = this.options.filter(option => option.toLowerCase().indexOf(value.toLowerCase()) === 0); + onChange(value: string): void { + this.filteredOptions = this.options.filter(option => option.toLowerCase().indexOf(value.toLowerCase()) !== -1); } } diff --git a/components/auto-complete/demo/options.ts b/components/auto-complete/demo/options.ts index f2e29ddfaa..cf150bd91a 100644 --- a/components/auto-complete/demo/options.ts +++ b/components/auto-complete/demo/options.ts @@ -9,7 +9,7 @@ import { Component, ViewEncapsulation } from '@angular/core'; placeholder="input here" nz-input [(ngModel)]="inputValue" - (ngModelChange)="onChange($event)" + (input)="onInput($event)" [nzAutocomplete]="auto" /> @@ -22,7 +22,8 @@ export class NzDemoAutoCompleteOptionsComponent { inputValue: string; options: string[] = []; - onChange(value: string): void { + onInput(e: Event): void { + const value = (e.target as HTMLInputElement).value; if (!value || value.indexOf('@') >= 0) { this.options = []; } else { diff --git a/components/auto-complete/demo/uncertain-category.ts b/components/auto-complete/demo/uncertain-category.ts index a4257c10b9..a711efda30 100644 --- a/components/auto-complete/demo/uncertain-category.ts +++ b/components/auto-complete/demo/uncertain-category.ts @@ -10,7 +10,7 @@ import { Component, ViewEncapsulation } from '@angular/core'; placeholder="input here" nz-input [(ngModel)]="inputValue" - (ngModelChange)="onChange($event)" + (input)="onChange($event)" [nzAutocomplete]="auto" /> @@ -20,22 +20,35 @@ import { Component, ViewEncapsulation } from '@angular/core'; - - {{ option.value }} 在 - + + Found {{ option.value }} on + {{ option.category }} - 区块中 - 约 {{ option.count }} 个结果 + {{ option.count }} results `, styles: [ ` + .global-search-item { + display: flex; + } + + .global-search-item-desc { + flex: auto; + text-overflow: ellipsis; + overflow: hidden; + } + .global-search-item-count { - position: absolute; - right: 16px; + flex: none; } ` ] @@ -44,8 +57,9 @@ export class NzDemoAutoCompleteUncertainCategoryComponent { inputValue: string; options: Array<{ value: string; category: string; count: number }> = []; - onChange(value: string): void { - this.options = new Array(this.getRandomInt(15, 5)) + onChange(e: Event): void { + const value = (e.target as HTMLInputElement).value; + this.options = new Array(this.getRandomInt(5, 15)) .join('.') .split('.') .map((_item, idx) => ({ diff --git a/components/auto-complete/nz-autocomplete-option.component.ts b/components/auto-complete/nz-autocomplete-option.component.ts index 4671c82192..e416945250 100644 --- a/components/auto-complete/nz-autocomplete-option.component.ts +++ b/components/auto-complete/nz-autocomplete-option.component.ts @@ -54,10 +54,12 @@ export class NzAutocompleteOptionComponent { constructor(private changeDetectorRef: ChangeDetectorRef, private element: ElementRef) {} - select(): void { + select(emit: boolean = true): void { this.selected = true; this.changeDetectorRef.markForCheck(); - this.emitSelectionChangeEvent(); + if (emit) { + this.emitSelectionChangeEvent(); + } } deselect(): void { diff --git a/components/auto-complete/nz-autocomplete-trigger.directive.ts b/components/auto-complete/nz-autocomplete-trigger.directive.ts index 30482a73d5..abf6cfa59a 100644 --- a/components/auto-complete/nz-autocomplete-trigger.directive.ts +++ b/components/auto-complete/nz-autocomplete-trigger.directive.ts @@ -26,6 +26,7 @@ import { ExistingProvider, Inject, Input, + NgZone, OnDestroy, Optional, ViewContainerRef @@ -33,7 +34,7 @@ import { import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'; import { fromEvent, merge, Subscription } from 'rxjs'; -import { delay, distinct, map } from 'rxjs/operators'; +import { delay, distinct, map, take, tap } from 'rxjs/operators'; import { NzAutocompleteOptionComponent } from './nz-autocomplete-option.component'; import { NzAutocompleteComponent } from './nz-autocomplete.component'; @@ -92,8 +93,9 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD constructor( private elementRef: ElementRef, - private _overlay: Overlay, + private overlay: Overlay, private viewContainerRef: ViewContainerRef, + private ngZone: NgZone, // tslint:disable-next-line:no-any @Optional() @Inject(DOCUMENT) private document: any ) {} @@ -124,6 +126,7 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD openPanel(): void { this.previousValue = this.elementRef.nativeElement.value; this.attachOverlay(); + this.updateStatus(); } closePanel(): void { @@ -210,8 +213,16 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD * Subscription data source changes event */ private subscribeOptionsChange(): Subscription { - return this.nzAutocomplete.options.changes.pipe(delay(0)).subscribe(() => { + const firstStable = this.ngZone.onStable.asObservable().pipe(take(1)); + const optionChanges = this.nzAutocomplete.options.changes.pipe( + tap(() => this.positionStrategy.reapplyLastPosition()), + delay(0) + ); + return merge(firstStable, optionChanges).subscribe(() => { this.resetActiveItem(); + if (this.panelOpen) { + this.overlayRef!.updatePosition(); + } }); } @@ -252,10 +263,11 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD return this.positionStrategy.positionChanges .pipe( map((position: ConnectedOverlayPositionChange) => position.connectionPair.originY), - distinct() + distinct(), + delay(0) ) .subscribe((position: VerticalConnectionPos) => { - this.nzAutocomplete.dropDownPosition = position; + this.nzAutocomplete.updatePosition(position); }); } @@ -269,7 +281,7 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD } if (!this.overlayRef) { - this.overlayRef = this._overlay.create(this.getOverlayConfig()); + this.overlayRef = this.overlay.create(this.getOverlayConfig()); } if (this.overlayRef && !this.overlayRef.hasAttached()) { @@ -279,15 +291,14 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD this.overlayBackdropClickSubscription = this.subscribeOverlayBackdropClick(); this.optionsChangeSubscription = this.subscribeOptionsChange(); } - this.nzAutocomplete.isOpen = this.panelOpen = true; + } + + private updateStatus(): void { + if (this.overlayRef) { + this.overlayRef.updateSize({ width: this.nzAutocomplete.nzWidth || this.getHostWidth() }); + } this.nzAutocomplete.setVisibility(); - this.overlayRef.updateSize({ width: this.nzAutocomplete.nzWidth || this.getHostWidth() }); - setTimeout(() => { - if (this.overlayRef) { - this.overlayRef.updatePosition(); - } - }, 150); this.resetActiveItem(); if (this.activeOption) { this.activeOption.scrollIntoViewIfNeeded(); @@ -303,7 +314,7 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD private getOverlayConfig(): OverlayConfig { return new OverlayConfig({ positionStrategy: this.getOverlayPosition(), - scrollStrategy: this._overlay.scrollStrategies.reposition(), + scrollStrategy: this.overlay.scrollStrategies.reposition(), // default host element width width: this.nzAutocomplete.nzWidth || this.getHostWidth() }); @@ -322,19 +333,21 @@ export class NzAutocompleteTriggerDirective implements ControlValueAccessor, OnD new ConnectionPositionPair({ originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' }), new ConnectionPositionPair({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' }) ]; - this.positionStrategy = this._overlay + this.positionStrategy = this.overlay .position() .flexibleConnectedTo(this.getConnectedElement()) - .withPositions(positions) .withFlexibleDimensions(false) - .withPush(false); + .withPush(false) + .withPositions(positions); return this.positionStrategy; } private resetActiveItem(): void { - const index = this.nzAutocomplete.getOptionIndex(this.nzAutocomplete.activeItem); - if (this.nzAutocomplete.activeItem && index !== -1) { + const index = this.nzAutocomplete.getOptionIndex(this.previousValue); + this.nzAutocomplete.clearSelectedOptions(null, true); + if (index !== -1) { this.nzAutocomplete.setActiveItem(index); + this.nzAutocomplete.activeItem.select(false); } else { this.nzAutocomplete.setActiveItem(this.nzAutocomplete.nzDefaultActiveFirstOption ? 0 : -1); } diff --git a/components/auto-complete/nz-autocomplete.component.html b/components/auto-complete/nz-autocomplete.component.html index bf9efc03db..afabd335fe 100644 --- a/components/auto-complete/nz-autocomplete.component.html +++ b/components/auto-complete/nz-autocomplete.component.html @@ -4,7 +4,9 @@ [@.disabled]="noAnimation?.nzNoAnimation" [nzNoAnimation]="noAnimation?.nzNoAnimation" [@slideMotion]="dropDownPosition" - [class.ant-select-dropdown-hidden]="!showPanel" [ngClass]="nzOverlayClassName" [ngStyle]="nzOverlayStyle"> + [class.ant-select-dropdown-hidden]="!showPanel" + [ngClass]="nzOverlayClassName" + [ngStyle]="nzOverlayStyle">