From 7eb46340ea7dd864160d683e8c504fa32ae46302 Mon Sep 17 00:00:00 2001 From: Igor Milly Date: Mon, 14 Mar 2022 12:33:54 +0100 Subject: [PATCH] feat(autocomplete): add scroll strategy provider (#543) --- .../autocomplete-examples.module.ts | 4 +++ ...plete-scroll-strategy-provider-example.css | 0 ...lete-scroll-strategy-provider-example.html | 6 ++++ ...mplete-scroll-strategy-provider-example.ts | 28 +++++++++++++++++++ .../autocomplete-trigger.directive.ts | 28 +++++++++++++++---- .../src/autocomplete/autocomplete.md | 11 ++++++++ .../src/autocomplete/autocomplete.module.ts | 3 +- 7 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.css create mode 100644 projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.html create mode 100644 projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.ts diff --git a/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-examples.module.ts b/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-examples.module.ts index 68354b685..b67224814 100644 --- a/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-examples.module.ts +++ b/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-examples.module.ts @@ -9,6 +9,7 @@ import { AutocompleteDataBindingExampleComponent } from './autocomplete-data-bin import { AutocompleteDefaultRenderingExampleComponent } from './autocomplete-default-rendering/autocomplete-default-rendering-example'; import { AutocompleteFilteringExampleComponent } from './autocomplete-filtering/autocomplete-filtering-example'; import { AutocompleteOutlineExampleComponent } from './autocomplete-outline/autocomplete-outline-example'; +import { AutocompleteScrollStrategyProviderExampleComponent } from './autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example'; const EXAMPLES = [ AutocompleteBasicExampleComponent, @@ -16,6 +17,7 @@ const EXAMPLES = [ AutocompleteDefaultRenderingExampleComponent, AutocompleteFilteringExampleComponent, AutocompleteOutlineExampleComponent, + AutocompleteScrollStrategyProviderExampleComponent, ]; @NgModule({ @@ -40,6 +42,8 @@ export class AutocompleteExamplesModule { AutocompleteDefaultRenderingExampleComponent, 'autocomplete-filtering': AutocompleteFilteringExampleComponent, 'autocomplete-outline': AutocompleteOutlineExampleComponent, + 'autocomplete-scroll-strategy-provider': + AutocompleteScrollStrategyProviderExampleComponent, }; } } diff --git a/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.css b/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.css new file mode 100644 index 000000000..e69de29bb diff --git a/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.html b/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.html new file mode 100644 index 000000000..19c6c17c4 --- /dev/null +++ b/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.html @@ -0,0 +1,6 @@ + + + + {{ option }} + + diff --git a/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.ts b/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.ts new file mode 100644 index 000000000..1df7dd2b3 --- /dev/null +++ b/projects/ng-aquila/documentation/examples/autocomplete/autocomplete-scroll-strategy-provider/autocomplete-scroll-strategy-provider-example.ts @@ -0,0 +1,28 @@ +import { Overlay, ScrollStrategy } from '@angular/cdk/overlay'; +import { Component } from '@angular/core'; +import { NX_AUTOCOMPLETE_SCROLL_STRATEGY } from '@aposin/ng-aquila/autocomplete'; + +const words = `Chimpanzee,Chinchilla,Chipmunk,Coati,Cicada,Clam,Clownfish,Cobra,Cockroach,Cod,Condor,Constrictor,Coral,Cougar,Cow,Coyote,Coypu,Crab,Crane,Crane fly,Crawdad,Crayfish,Cricket,Crocodile,Crow`; + +function scrollStrategyFactory(overlay: Overlay): () => ScrollStrategy { + return () => overlay.scrollStrategies.close({ threshold: 100 }); +} + +/** + * @title Scroll Strategy Provider Example + */ +@Component({ + selector: 'autocomplete-scroll-strategy-provider-example', + templateUrl: './autocomplete-scroll-strategy-provider-example.html', + styleUrls: ['./autocomplete-scroll-strategy-provider-example.css'], + providers: [ + { + provide: NX_AUTOCOMPLETE_SCROLL_STRATEGY, + useFactory: scrollStrategyFactory, + deps: [Overlay], + }, + ], +}) +export class AutocompleteScrollStrategyProviderExampleComponent { + options = words.split(','); +} diff --git a/projects/ng-aquila/src/autocomplete/autocomplete-trigger.directive.ts b/projects/ng-aquila/src/autocomplete/autocomplete-trigger.directive.ts index c2e7d3c89..d60fc5b0c 100644 --- a/projects/ng-aquila/src/autocomplete/autocomplete-trigger.directive.ts +++ b/projects/ng-aquila/src/autocomplete/autocomplete-trigger.directive.ts @@ -1,7 +1,7 @@ import { Directionality } from '@angular/cdk/bidi'; import { coerceNumberProperty, NumberInput } from '@angular/cdk/coercion'; import { DOWN_ARROW, ENTER, ESCAPE, TAB, UP_ARROW } from '@angular/cdk/keycodes'; -import { FlexibleConnectedPositionStrategy, Overlay, OverlayConfig, OverlayRef, PositionStrategy, ViewportRuler } from '@angular/cdk/overlay'; +import { FlexibleConnectedPositionStrategy, Overlay, OverlayConfig, OverlayRef, PositionStrategy, ScrollStrategy, ViewportRuler } from '@angular/cdk/overlay'; import { TemplatePortal } from '@angular/cdk/portal'; import { DOCUMENT } from '@angular/common'; import { @@ -12,6 +12,7 @@ import { forwardRef, Host, Inject, + InjectionToken, Input, NgZone, OnChanges, @@ -39,6 +40,21 @@ export const NX_AUTOCOMPLETE_VALUE_ACCESSOR: any = { multi: true, }; +/** Injection token that determines the scroll handling while a autocomplete is open. */ +export const NX_AUTOCOMPLETE_SCROLL_STRATEGY = new InjectionToken<() => ScrollStrategy>('nx-autocomplete-scroll-strategy'); + +/** @docs-private */ +export function NX_AUTOCOMPLETE_SCROLL_STRATEGY_PROVIDER_FACTORY(overlay: Overlay): () => ScrollStrategy { + return () => overlay.scrollStrategies.reposition(); +} + +/** @docs-private */ +export const NX_AUTOCOMPLETE_SCROLL_STRATEGY_PROVIDER = { + provide: NX_AUTOCOMPLETE_SCROLL_STRATEGY, + useFactory: NX_AUTOCOMPLETE_SCROLL_STRATEGY_PROVIDER_FACTORY, + deps: [Overlay], +}; + /** * Creates an error to be thrown when attempting to use an autocomplete trigger without a panel. */ @@ -111,6 +127,9 @@ export class NxAutocompleteTriggerDirective implements ControlValueAccessor, OnD /** Subscription to direction changes */ private _dirChangeSubscription = Subscription.EMPTY; + /** Strategy factory that will be used to handle scrolling while the autocomplete panel is open. */ + private _scrollStrategyFactory = this._defaultScrollStrategyFactory; + /** The autocomplete panel to be attached to this trigger. */ @Input('nxAutocomplete') autocomplete!: NxAutocompleteComponent; @@ -233,6 +252,7 @@ export class NxAutocompleteTriggerDirective implements ControlValueAccessor, OnD @Optional() @Host() private _nxFormField: NxFormfieldComponent, @Optional() @Host() private _nxWordField: NxWordComponent, @Optional() @Inject(DOCUMENT) private _document: any, + @Inject(NX_AUTOCOMPLETE_SCROLL_STRATEGY) private _defaultScrollStrategyFactory: () => ScrollStrategy, private _viewportRuler?: ViewportRuler, ) { if (typeof window !== 'undefined') { @@ -631,7 +651,7 @@ export class NxAutocompleteTriggerDirective implements ControlValueAccessor, OnD private _getOverlayConfig(): OverlayConfig { return new OverlayConfig({ positionStrategy: this._getOverlayPosition(), - scrollStrategy: this._scrollStrategy(), + scrollStrategy: this._scrollStrategyFactory(), minWidth: this._getHostWidth(), direction: this._dir?.value || 'ltr', }); @@ -669,10 +689,6 @@ export class NxAutocompleteTriggerDirective implements ControlValueAccessor, OnD return this._positionStrategy; } - private _scrollStrategy() { - return this._overlay.scrollStrategies.reposition(); - } - private _getConnectedElement(): ElementRef { return this._formField ? this._formField.getConnectedOverlayOrigin() : this._element; } diff --git a/projects/ng-aquila/src/autocomplete/autocomplete.md b/projects/ng-aquila/src/autocomplete/autocomplete.md index cae371b22..a3216faad 100644 --- a/projects/ng-aquila/src/autocomplete/autocomplete.md +++ b/projects/ng-aquila/src/autocomplete/autocomplete.md @@ -59,6 +59,17 @@ Please note that this is an **Expert styling option**. This means that the outli +### Global Settings + +If you want to use a custom scroll strategy for all of your autocompletes, you can use the `NX_AUTOCOMPLETE_SCROLL_STRATEGY` injection token with a factory provider. The `Overlay` service from `@angular/cdk/overlay` offers 4 different scroll strategy options: + +- **reposition:** allow background scroll, the overlay moves with the background (default). +- **close:** allow background scroll, closes the overlay on scroll. +- **block:** disallow background scroll, the overlay does not move. +- **noop:** allow background scroll, the overlay does not move. + + + ### Accessibility The autocomplete can be accessed via keyboard. You can trigger the search by simply start typing in the input. After the overlay popped up, you can use ARROW_UP and ARROW_DOWN to focus on the desired element. Hitting SPACE or ENTER selects the value however ESC or TAB closes the autocomplete. diff --git a/projects/ng-aquila/src/autocomplete/autocomplete.module.ts b/projects/ng-aquila/src/autocomplete/autocomplete.module.ts index 4e048b55b..b5037a348 100644 --- a/projects/ng-aquila/src/autocomplete/autocomplete.module.ts +++ b/projects/ng-aquila/src/autocomplete/autocomplete.module.ts @@ -5,11 +5,12 @@ import { NgModule } from '@angular/core'; import { NxAutocompleteComponent } from './autocomplete.component'; import { NxAutocompleteOptionComponent } from './autocomplete-option.component'; -import { NxAutocompleteTriggerDirective } from './autocomplete-trigger.directive'; +import { NX_AUTOCOMPLETE_SCROLL_STRATEGY_PROVIDER, NxAutocompleteTriggerDirective } from './autocomplete-trigger.directive'; @NgModule({ declarations: [NxAutocompleteComponent, NxAutocompleteOptionComponent, NxAutocompleteTriggerDirective], exports: [NxAutocompleteComponent, NxAutocompleteOptionComponent, NxAutocompleteTriggerDirective], imports: [CommonModule, OverlayModule, A11yModule], + providers: [NX_AUTOCOMPLETE_SCROLL_STRATEGY_PROVIDER], }) export class NxAutocompleteModule {}