-
Notifications
You must be signed in to change notification settings - Fork 6.8k
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(cdk/scrolling): make scroller element configurable for virtual scrolling #24394
feat(cdk/scrolling): make scroller element configurable for virtual scrolling #24394
Conversation
9e5b75b
to
3bfb3fe
Compare
Any Ideas how |
Hi @spike-rabbit thanks for working on this!
|
25875b1
to
5f4609d
Compare
Thx a lot for your feedback @mmalerba. While adopting your feedback, I run into another issue, or I am just missing something. My problem in general is, that So before I take actions on splitting the scrollTo(scrollHeight: number, clientHeight: number, scrollWidth: number, clientWidth: number, scrollTop: number, scrollLeft: number, options: ExtendedScrollToOptions): void {
...
} With my most recent commit I just declared the |
Ah that's unfortunate that the APIs don't match up exactly, but I think the solution you have is good, having a special subclass for the window scrollable 👍 |
@spike-rabbit This is absolutely fantastic. Thank you for working on this! I think this feature is one of the only things holding us back from using the cdk virtual-scroll API. What are the next steps with this PR? Is there anything anyone can do to help? (Looking for ways to make sure this happens!) Happy to assist if I can. I'm trying to test it right now. |
@lincolnthree I need to complete documentation, tests and probably clean up some stuff. I am very confident, that I can do this already in April, but most likely not next week. Please let me know the outcome of your tests. I only tried it in the cdk demo app. |
@spike-rabbit Awesome! Really looking forward to it. So... I'm still working on it... but it appears the CI build artifacts have expired/timed out. Had a little trouble getting things linked, but seems like I'm there. I was able to build @angular/cdk and get it installed. Took a bit of hacking since apparently the Angular compiler doesn't like symlinks by default. Regarding documentation, yes. I'm now trying to figure out how exactly to select and link the scrollable element to the virtual-scroll-viewport. It looks like your example is fairly straightforward in the CDK sandbox. Is there a way to passing in an ElementRef or HTMLElement programmatically, or via inputs? Trying to figure out how I can plug in. For instance, in my case, my scrolling element resides within the Shadow DOM of a 3rd party component, and that's currently passed into our existing virtual-scroll implementation directly. Example of what I mean:
|
Trying to provide my own |
Damn. So unless there's a way to lazily instantiate the I notice there is an abstract method to get the window offset, but why not also one to provide the element itself? E.g.:
|
Hmm, I'll wait till I hear back. I don't think I'm approaching this the right way. That said, I think the ability to declaratively pass in a scroll-container or scrollable element is fairly crucial. E.g. For the scenario where a |
I was able to copy enough code to create a CdkScrollable implementation that provides a deferred native element, but I can't seem to get the scrollable viewport to pick it up. It's not pretty, and I think being able to directly provide a scrollable element in the viewport component itself is the best solution I can think of. I will try that next. |
I have to go for the night, but this is what I'm thinking:
Then this is all it takes:
|
Okay, so I finally got things wired up (with my slight modification to set the scrolling container directly) and was able to start testing. This feature works exactly as it should! YES. With my modification I was able to directly assign the scroll container and that works perfectly, too. (Small note, the reason this modification -- or something like it -- to set the scroll container is necessary after construction (at init time) is for compatibility with the Ionic framework and others like it.) I noticed that this does not seem to play super nicely with |
Update. I have had little luck getting this to work with the experimental auto-size feature. I am probably missing something simple. |
@lincolnthree I am not sure, if your solution is a good idea. I would expect that linking to another container in a 3rd party library is a rare edge case. I would guess, that in those scenarios it is better to provide a custom The only challenging part about the ion-content is, that the container is asynchronously resolved. Something like this should work (not tested): @Directive({
selector: 'ion-content[virtual-scrollable], ion-content[virtualScrollable]',
providers: [{provide: VIRTUAL_SCROLLABLE, useExisting: IonContentVirtualScrollable }],
})
export class IonContentVirtualScrollable extends CdkVirtualScrollableElement {
protected _elementScrolled: Observable<Event> = new Observable((observer: Observer<Event>) =>
this.ngZone.runOutsideAngular(async () => {
const ionScrollElement = await this.ionContent.getScrollElement();
fromEvent(ionScrollElement, 'scroll')
.pipe(takeUntil(this._destroyed))
.subscribe(observer),
}),
);
constructor(
private IonContent: IonContent,
scrollDispatcher: ScrollDispatcher,
ngZone: NgZone,
@Optional() dir: Directionality,
) {
super(undefined!, scrollDispatcher, ngZone, dir);
this.ionContent.getScrollElement().then(ionScrollElement => {
this.elementRef = new ElementRef(ionScrollElement);
ionScrollElement.classList.add('cdk-virtual-scrollable');
});
}
} and using it like this: <ion-content virtual-scrollable>
<cdk-virtual-scroll-viewport>
...
</cdk-virtual-scroll-viewport>
</ion-content> |
5f4609d
to
4061ffc
Compare
@mmalerba This is ready for a full review now. Everything you addressed before should be fixed. Tests and documentation are updated as well. Please let me know if there is more to do. |
@spike-rabbit Just a heads up that @mmalerba is out right now and should be able to resume the review in May |
@spike-rabbit Interesting. That looks like it should work. I did not think about passing undefined and then setting the elementRef manually. Though, to be honest, asking a developer to do this, versus just setting the element... this seems like a much more complex approach for what is really just setting a value. Though if we are respecting conventions and patterns, I get it. The remaining question I have about this, is how would this directive work if the This directive and it's provided value would need to be able to cross the component boundary. Maybe this is an angular provider question and not so much a question for this PR.
Not really 100% sure how this goes. Or I suppose the virtual scroll itself could be contained in the component, but that complicates things a bit. I'll give this a try and report back. |
@spike-rabbit Thanks for the changes this looks good to me. Just one last thing is I want to have a discussion with the rest of the team about the naming for the new directives (always the hardest part of programming 🙄 ). I'll get back to you next week on that, in the mean time LGTM |
5e65e1f
to
c1d1a11
Compare
@mmalerba can you please help me to solve this error:
This happens, when I try to build, test or to accept API changes. I already deleted |
Oh yeah that happened to me recently too. Some combination of the below finally fixed it:
|
@mmalerba thx for the tip. It works now. Hope that everything is ready to merge |
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.
Yes, all looks good on your side. Now I just have to run it against the tests in Google's codebase to make sure it doesn't break anything
@@ -69,11 +73,7 @@ cdk-virtual-scroll-viewport { | |||
// set if it were rendered all at once. This ensures that the scrollable content region is the | |||
// correct size. | |||
.cdk-virtual-scroll-spacer { | |||
position: absolute; |
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.
@spike-rabbit I started looking into why some tests were failing internally with this change, and it looked like some people were setting display: flex
on the viewport. Without this position: absolute
the spacer is collapsing and throwing off the scrollbar.
I think we could definitely question why they're making it display: flex
, as I don't see any real reason to do that, but I think we could help prevent unexpected breakages by just slapping a flex: 0 0 auto
on here.
I also notice that below you still have right: 0
and left: auto
which can be removed, now that its no longer position: absolute
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.
@mmalerba changed as you requested
…crolling Decouples the scroller from the virtual-scroll-viewport which allows library consumers to use any parent element as a scroller. This is especially helpful when building SPAs with a single global scrollbar. Closes angular#13862
a285fe0
to
a37dbee
Compare
Demo for anyone looking for it available at https://stackblitz.com/run?file=src%2Fapp%2Fcdk-virtual-scroll-window-scrolling-example.html |
@tomasdev I think that link isn't working (at least it's not for me?) Thanks! |
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. |
Decouples the scroller from the virtual-scroll-viewport which allows library consumers
to use any parent element as a scroller. This is especially helpful when building SPAs
with a single global scrollbar.
Closes #13862
@mmalerba this is first draft, test and docs updates are missing. But I would like to have your feedback regarding certain points.
WDYT about the API changes in general?
There are a couple of lines, only to maintain backward compatibility. I am not sure if it's worth it, as I would expect that the required changes on applications could be done using schematics. Changing
<cdk-virtual-scroll-viewport ...
to<cdk-virtual-scroll-viewport cdk-virtual-scrollable-element ...
should be sufficient.I had some problems linking it to the global-scrollbar. As commented in the code, although documentElement is the scrolling element, no scroll event is fired. The current approach is the shortest one, but seems a little ugly to me. Instead of using html-elements in scrollable, using an adaptor could be an option as well.
As done multiple times, the conversion from
'top' | 'left' | 'right' | 'bottom' | 'start' | 'end'
to'left' | 'top' | 'right' | 'bottom'
can be extracted to a new method. But where should I put this? Iscdk/src/platform/features/scrolling
the correct place?