Skip to content

Commit

Permalink
feat(autocomplete): add scroll strategy provider (#543)
Browse files Browse the repository at this point in the history
  • Loading branch information
Igor Milly authored and GitHub Enterprise committed Mar 14, 2022
1 parent bc1ae19 commit 7eb4634
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@ 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,
AutocompleteDataBindingExampleComponent,
AutocompleteDefaultRenderingExampleComponent,
AutocompleteFilteringExampleComponent,
AutocompleteOutlineExampleComponent,
AutocompleteScrollStrategyProviderExampleComponent,
];

@NgModule({
Expand All @@ -40,6 +42,8 @@ export class AutocompleteExamplesModule {
AutocompleteDefaultRenderingExampleComponent,
'autocomplete-filtering': AutocompleteFilteringExampleComponent,
'autocomplete-outline': AutocompleteOutlineExampleComponent,
'autocomplete-scroll-strategy-provider':
AutocompleteScrollStrategyProviderExampleComponent,
};
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<input type="text" [nxAutocomplete]="auto" />
<nx-autocomplete #auto="nxAutocomplete">
<nx-autocomplete-option *ngFor="let option of options" [value]="option">
{{ option }}
</nx-autocomplete-option>
</nx-autocomplete>
Original file line number Diff line number Diff line change
@@ -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(',');
}
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -12,6 +12,7 @@ import {
forwardRef,
Host,
Inject,
InjectionToken,
Input,
NgZone,
OnChanges,
Expand Down Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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') {
Expand Down Expand Up @@ -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',
});
Expand Down Expand Up @@ -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;
}
Expand Down
11 changes: 11 additions & 0 deletions projects/ng-aquila/src/autocomplete/autocomplete.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,17 @@ Please note that this is an **Expert styling option**. This means that the outli
</div>
### 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.
<!-- example(autocomplete-scroll-strategy-provider) -->
### 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.
3 changes: 2 additions & 1 deletion projects/ng-aquila/src/autocomplete/autocomplete.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}

0 comments on commit 7eb4634

Please sign in to comment.