angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.35k stars 6.74k forks source link

Virtual scrolling helpers / utilities. #823

Closed jelbourn closed 6 years ago

jelbourn commented 8 years ago

Similar to the md-virtual-repeat in Angular Material 1.

natcohen commented 8 years ago

Would be good to implement dynamic height (https://github.com/angular/material/issues/4314)

elvisbegovic commented 8 years ago

Does someone know a repo do this virtual scroll instead of ngFor ? Today we have a very large set of data, it's primordial to begin/HAVE this feature instead of something like "tooltip" or so ! @jelbourn Displaying big data is important today please begin with something hard instead of "tooltip"

ps: https://developers.google.com/web/updates/2016/07/infinite-scroller

DennisSmolek commented 8 years ago

@istiti Polymer has <iron-list> Here and Demos Here

Please recognize that you are asking about a feature that most projects don't need/use and is a technical challenge to put into a library in a fully formed, universal way... You could probably write your own version, but it might not be what I would need...

Tooltip is a super easy use case for portals and overlay's which are core to everything from menu's to dialogs so is rather simple to release and common enough that most use cases fit.

The link you gave has a link to his source code and it's only 400ish lines. I bet you could make a ng2 version and contributing it back to the community for free would be awesome!

elvisbegovic commented 8 years ago

@DennisSmolek "Infinite scrollers pop up all over the internet. Google Music’s artist list is one, Facebook’s timeline is one and Twitter’s live feed is one as well" IMHO infinite scroll is technik people need to have to discharge their DOM! Still more today we have big data.

Update

Impossible to get iron list working (very comlpicate) if you have an github repo doing virtual Dom, you're welcome

laserus commented 7 years ago

@istiti Have you tried this https://github.com/vaadin/angular2-polymer

https://vaadin.com/blog/-/blogs/using-polymer-components-in-angular-2

elvisbegovic commented 7 years ago

yes but this add more complexities to my app ... really a bad choice but I find angular2-data-table which do work very awesome thanks

elvisbegovic commented 7 years ago

ETA?

Klaster1 commented 7 years ago

I've ported the old one and wonder if I there's some form of spec available so I can align my implementation with it. The mdVirtualRepeat is almost (as in line-to-line) the same, but structural repeater had to be made by scratch based on ngFor and mdVirtualRepeat.

bryanrideshark commented 7 years ago

@Klaster1 , any chance you could fork material2 and add your work to the library? If there was at least an initial PR we could get some momentum going behind this.

bryanrideshark commented 7 years ago

ngx-datatable has an implementation of virtual scroll.

I wonder if that couldn't be easily brought in?

savaryt commented 7 years ago

@jelbourn I've made a naive implementation of a templatizable-virtual-repeat that work great for basic use-cases. However, the item repeated must have a fixed height. For now the virtual-repeat only supports: itemNumber * itemHeight / maxHeight of HTMLElement of the browser which is 33554400px in Chrome. So the number of items to be virtualized is still limited and relative to their heights.

If this sounds good to you, I can make a PR with the initial version and if the components pleases most I can work on the maxHeight issue.

Let me know if you're interested.

jelbourn commented 7 years ago

@thibaultsavary we want to explore solutions for non fix-sized items in material2.

bryanrideshark commented 7 years ago

@jelbourn is that the sort of thing that can be implemented in a version bump down the road? Variable height is a tricky issue to solve with virtual repeaters, and I'm not sure insisting upon its inclusion is a realistic goal.

If we could at least get feature parity with Angular Material 1.0, it would be a massive help; Our company is pretty dependent on md-virtual-repeat, and its lack of support in Angular Material 2.0 is a bit of a blocker for us to upgrade to Angular ^2.

To be sure, flexible height would be a great feature, I'm just not sure it's as much of a requirement as having virtual repeat in the first place.

laserus commented 7 years ago

@jelbourn I fully agree with @bryanrideshark for virtual scroll to be exact in height is not top priority. Exact position affects scrollbar position on the right, but normally it is only a visual effect.

natcohen commented 7 years ago

@bryanrideshark & @laserus I don't agree with you guys... if the team implements the v1 (from material 1), a better version will probably never be explored! The team's time is limited and they should focus on innovation rather than existing technologies

elvisbegovic commented 7 years ago

+1 for innovation

ps:wait this feature since 5 months

ronwang01 commented 7 years ago

+1 for the flexible height.

bryanrideshark commented 7 years ago

@natcohen all of what will / will not happen is speculation unless we're actually decision makers in the matter, IE, core members of the team.

As this is a blocking issue for other things (autocomplete, md-select), would someone on the team be able to provide some sort of feedback as to where this issue stands?

harivrdhn commented 7 years ago

+1 for the flexible height

robconrad commented 7 years ago

+1 need this badly!

Hacklone commented 7 years ago

I have an implementation for virtual grids: https://github.com/Hacklone/angular2-cool-infinite-grid Maybe grids could be part of virtual scrolling too :)

zeves095 commented 7 years ago

there aren't virtual scroll component In milestones. Are you planning to implement it?

buu700 commented 7 years ago

https://github.com/dinony/od-virtualscroll is working great in my project, and so far is the only one I've tested that I could get working (the others might not have liked @angular/flex-layout, not sure).

It doesn't yet support dynamic item height, so for now we're just using it in a feature branch, but otherwise seems like a really good implementation.

mackelito commented 7 years ago

@buu700 do you know if it supports flexLayout?

buu700 commented 7 years ago

@mackelito, yep, they seem to be working well together; I just had to include a small CSS workaround. This is what my implementation looks like:

od-virtualscroll, od-virtualrow {
    width: 100%;
}

...

<div fxFlexFill fxLayout='column'>
    <od-virtualscroll fxFlexFill>
        <ng-template let-item let-row='row'>
            ...
        </ng-template>
    </od-virtualscroll>
</div>

Also potentially helpful (not material/flex-layout-specific): https://github.com/dinony/od-virtualscroll/issues/2#issuecomment-301191176

WhatzzUp commented 7 years ago

+1 for the flexible height.

MadUser commented 7 years ago

What do you mean by flexible height, Do you expect the repeater to calculate the height by itself and assume that all items has the same height or you wish for every item to have it's own different height? I am asking because I already implemented this component and the former wish is crazy. The first is simple though, before creating the components loop, just build the first component and then calculate it's height...

Klaster1 commented 7 years ago

@MadUser customizable height calculation function might be good enough. Default implementation will measure first item or use number value from binding/config object. If you can calculate each item dimensions reliably, variable size will work. For example, if each virtual list item is another list of items of predefined size, just multiply item height and items amount (in simpliest case).

damiendube commented 7 years ago

I'm currently using this one: https://github.com/rintoj/angular2-virtual-scroll Works great

elineopsommer commented 7 years ago

Any updates on this?

natcohen commented 7 years ago

@elineopsommer they have updated the feature status in the info page to "planned Q3 2017"... Q3 has just started so just be patient :)

azarus commented 7 years ago

@elineopsommer where is the info page?

azarus commented 7 years ago

Huh after reading through the comments i am surprised how complicated you guys want to make it. Isn't enough just to set the scroll distance for triggering an event to load more data. I see no point of being unable to be innovative with this. A working version that works simply should be enough and covers the most use cases. You can then be innovative and add more features?

luanmm commented 7 years ago

Some people disagree, @azarus. Why would you be on a team that is commited to create something with the best design principles and will just ignore this fact to create something that is already there? If your use case is simple, just work with some third-party library (or make a component) that fulfill your needs. The team cannot just start with something simple now, before designing with all cenarios in mind, as this may lead to a bad/wrong spec to other more complex cenarios.

Following your example, there is already other projects that can do what your want. For instance: https://github.com/rintoj/angular2-virtual-scroll. This is a nice implementation, but doesn't follow Angular Material principles. I think that's why the team is taking "so long" to implement the entire library with the best UI components in mind: design everything really well.

In a project that I am participating now, an use case for the virtual repeat component is a grid of images, that I load records from a service. My intent with this is to show it to the user like I would do using a RecyclerView (the Android component). And, in my opinion, this is where virtual scroll could be taken: a "mimic" of a RecyclerView that allows us to display an interesting UI without loading all the records upfront, but with the items "size" already defined (as we can run a simple count in database to check this quickly). This will help us to deliver better UI/UX to the user: a nice component to interact with and with great performance too.

azarus commented 7 years ago

The scrolling is already implemented in material but there are no such events yet as far as i see :/

luanmm commented 7 years ago

I think we aren't talking about the same thing here, @azarus. This issue is about tracking the Virtual Scroll/Repeat implementation for Material UI of Angular 2. It's not implemented yet. Not even designed.

The only news from it is an update (a couple of days ago) regarding the plan to start designing this component, that was postponed to Q4 this year.

Anyway... I have a lot of expectations about this component and hope to see it covering complex use cases too, not only what we already can do with any UI library today. This is what I think the team behind Material wants too and the work to polish everything is something big, but the results tend to be very promising.

elvisbegovic commented 7 years ago

One year later...

azarus commented 7 years ago

Just wait for them as they said they gona reinvent the wheel in an innovative way. :) such a joke.

cgatian commented 7 years ago

@azarus as one that is inspired by the Material team and their work I take comments like this as hurtful to this community. I understand you're frustrated with the lack of progress on this particular issue, but the team has been working their ass off on bringing core functionality with i18n, a11y, and the cdk. Your comments have added zero benefit to this thread.

I ask that you please resign from commenting.

manju-reddys commented 7 years ago

I found brilliant solution from slickgrid. This is basically handles unlimited records of any size (I don't think variable height can be handled in this case) and I have implemented the solution preview, comments added. This solution performance is too good compare to any solutions exist today. May be material team can consider to adopt it?

azarus commented 7 years ago

@cgatian then stop mentioning me in your fan comments? I do like material but this is slightly anoing how no progress is shown regarding this feature. If a complaint is hurtful because the team puts resources into reinvention rather than delivering it then it better be damn good?

elvisbegovic commented 7 years ago

@azarus +1

It's like google is very cool and have no profit to make all developer use angular or other. All is open source open source open source open source lol

This thread need tobe blocked

tolemac commented 7 years ago

Yep, need to be blocked until it will be done or in progress.

naveedahmed1 commented 7 years ago

Also take a look at https://github.com/tbranyen/hyperlist , non angular pure js version.

Toxicable commented 7 years ago

@jelbourn I know this isn't planned for post beta but was wondering if there was any API proposals floating around for this? I've been looking at a few different ways this could be implemented but wanted to check to see if what I've come up matches anything that the team might already have in mind.

Ploppy3 commented 7 years ago

Hello, Here is my own implementation of the virtual-scroll, inspired from one of AngularJs but coded by me, it does not support dynamic height of items but has really great performances (works perfectly well on CPU 6x slowdown with a fade-in animation for items).

Usage:

<optimized-list [items]="products" [itemHeight]="73" [offset]="2" (update)="optimizedList = $event">
  <!-- It supports animations: -->
  <div [@reveal] *ngFor="let product of optimizedList">
    {{product.name}}
  </div>
</optimized-list>

nb: "offset" represents the number of element preloaded (item rendered but not in the view) to prevent "pop-in" effect. This parameter is optional and default to 0, it's completely OK to keep it at default but you should add a fade-in animation. A really good compromise is to set it to 2 with a fade-in animation. It performs really well on low-end devices.

component.html A "fake-scroller" is an empty box in which the user can scroll, it has the total height of the list, the content is not in this "fake-scroller" but on top and will be translated using the css translateY function.

<div id="fake-scroller" [style.height]="scrollHeight + 'px'"></div>
<div id="content-wrapper" [style.transform]="'translateY(' + translateY + 'px)'">
  <ng-content></ng-content>
</div>

component.ts

import { Component, OnInit, OnChanges, SimpleChanges, Input, Output, EventEmitter, Renderer, ElementRef, HostListener } from '@angular/core';

@Component({
  selector: 'optimized-list',
  templateUrl: './optimized-list.component.html',
  styleUrls: ['./optimized-list.component.css']
})
export class OptimizedListComponent implements OnChanges {

  /*
  My own implementation of a virtual-scroll component
  ~Robin
  */

  @Input() items: any[]; //the items to display
  @Input() itemHeight: number = 20;
  @Input() offset: number = 0;
  @Output() update: EventEmitter<any[]> = new EventEmitter<any[]>();

  @HostListener('scroll') onScroll = function () {
    this.refresh();
  }

  public scrollHeight: number;
  public translateY: number;
  private visibleItems: any[] = [];

  constructor(
    private renderer: Renderer,
    private elementRef: ElementRef,
  ) { }

  ngOnChanges(changes: SimpleChanges) {
    for (let propName in changes) {
      if (propName == 'items') {
        this.scrollHeight = this.items.length * this.itemHeight + 88; //  + 88 // offset bottom
        //This offset is not necessary but I think the list should support both top and bottom offsets via parameters
        this.refresh();
      }
    }
  }

  private refresh() {
    let height: number = this.elementRef.nativeElement.clientHeight;
    let scrollTop: number = this.elementRef.nativeElement.scrollTop;
    let visual_start: number = Math.floor(scrollTop / this.itemHeight);
    let offset_start: number = Math.max(Math.floor(scrollTop / this.itemHeight) - this.offset, 0);
    let offset_end: number = Math.min(Math.ceil((height + scrollTop) / this.itemHeight) + this.offset, this.items.length);
    this.translateY = Math.min(scrollTop - (visual_start - offset_start) * this.itemHeight - (scrollTop % this.itemHeight), this.items.length * this.itemHeight);
    this.visibleItems = this.items.slice(offset_start, offset_end);
    this.update.next(this.visibleItems);
  }

}

component.css Nothing special about the css:

:host{
  display: block;
  position: relative;
  overflow: hidden;
  overflow-y: scroll;
  will-change: transform;
}
#fake-scroller{
  height: 100%;
}
#content-wrapper{
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
ruant commented 6 years ago

@jelbourn, any news on the progress of this? It's Q4 now isn't it? 😃

jelbourn commented 6 years ago

@mmalerba is working on it- it's a large project, so it was started in Q4 and is planned to wrap up in 2018.

Ploppy3 commented 6 years ago

@jelbourn will it support dynamic height of elements? It is a really important feature in my opinion.

jelbourn commented 6 years ago

Yes, that is something we aim to support (and one of the reasons it's a larger undertaking)