-
Notifications
You must be signed in to change notification settings - Fork 6.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(overlay): add scroll handling strategies #4293
Conversation
private _scrollSubscription: Subscription|null = null; | ||
private _overlayRef: OverlayRef; | ||
|
||
constructor(private _scrollDispatcher, private _scrollThrottle = 0) { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing type on _scrollDispatcher
private _scrollSubscription: Subscription|null = null; | ||
private _overlayRef: OverlayRef; | ||
|
||
constructor(private _scrollDispatcher) { } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing type on _scrollDipstacher
?
src/lib/core/overlay/overlay.spec.ts
Outdated
fakeScrollStrategy = { | ||
attach: jasmine.createSpy('attach spy'), | ||
enable: jasmine.createSpy('enable spy'), | ||
disable: jasmine.createSpy('disable spy') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rather than having spies, it would be slightly more accurate to just store attachedOverlay
and set isEnabled
and make assertions against those.
(with a spy technically you could do something like call enabled(); disabled();
and have it still pass)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The main reason I avoided adding isAttached
and isEnabled
was that I wanted to keep the ScrollStrategy
interface as lean as possible. Also, apart from unit tests, I'm not sure that they provide a lot of value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant only in the fake implementation for tests
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, got it. I've updated the tests.
@@ -218,6 +220,7 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy { | |||
overlayState.hasBackdrop = true; | |||
overlayState.backdropClass = 'cdk-overlay-transparent-backdrop'; | |||
overlayState.direction = this.dir; | |||
overlayState.scrollStrategy = new RepositionScrollStrategy(this._scrollDispatcher); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a follow-up PR: rather than having menu, select, etc. all directly use RepositionScrollStrategy
, we should have a provider that can configure the behavior more globally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good, although we'd have to have at least two: one for the global overlays and one for the connected ones.
if (!this._scrollSubscription) { | ||
this._scrollSubscription = this._scrollDispatcher.scrolled(null, () => { | ||
if (this._overlayRef.hasAttached()) { | ||
this._overlayRef.detach(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It doesn't look like anything communicates the fact that the overlay detached back to the component, which would make their own state be out of sync.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The OverlayRef
calls the disable
method when it detaches and when it is disposed: https://github.com/angular/material2/pull/4293/files#diff-d4ca44eeaacca5fbb90029f947afc1e0R82
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I meant the other way around- for example, if the overlay for MdMenuTrigger
is closed due to scrolling, nothing tells MdMenuTrigger
that this has happened and its _menuOpen
state will be wrong
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Got it. We should add a detach
observable to the OverlayRef
IMO. We already do it on the ConnectedOverlayDirective
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds reasonable to me
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added the observables as discussed. They're not being used anywhere right now since nothing uses the CloseScrollStrategy
. Also I initially wanted to have the outputs on the ConnectedOverlayDirective
proxy the ones on the overlay ref, but it's not possible since the ref gets created lazily before attaching.
src/lib/core/overlay/overlay-ref.ts
Outdated
/** Returns an observable that emits when the overlay has been detached. */ | ||
onDetach(): Observable<void> { | ||
return this._onDetach.asObservable(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make these getters called attachments
and detachments
? I kind of want to move away from the onAction
-style naming for observables
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@crisbeto needs rebase |
* Adds the `scrollStrategy` option to the overlay state, allowing the consumer to specify what scroll handling strategy they'd want to use. Also includes a `ScrollStrategy` interface that users can utilize to build their own strategies. * Adds the `RepositionScrollStrategy`, `CloseScrollStrategy` and `NoopScrollStrategy` as initial, out-of-the-box strategies. * Sets the `RepositionScrollStrategy` by default on all the connected overlays and removes some repetitive logic from the tooltip, autocomplete, menu and select. **Note:** I'll add a `BlockScrollStrategy` in a follow-up PR. I wanted to keep this one shorter. Relates to angular#4093.
031e4d7
to
8558bae
Compare
How does one use these scroll strategies on a MdDialog? Does that require a separate change? |
The dialog currently has a scroll strategy to disable scrolling. We're still working on a way to be able to override the strategy per component. |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
scrollStrategy
option to the overlay state, allowing the consumer to specify what scroll handling strategy they'd want to use. Also includes aScrollStrategy
interface that users can utilize to build their own strategies.RepositionScrollStrategy
,CloseScrollStrategy
andNoopScrollStrategy
as initial, out-of-the-box strategies.RepositionScrollStrategy
by default on all the connected overlays and removes some repetitive logic from the tooltip, autocomplete, menu and select.Note: I'll add a
BlockScrollStrategy
in a follow-up PR. I wanted to keep this one shorter.Relates to #4093.