GithubHelp home page GithubHelp logo

dhilt / ngx-ui-scroll Goto Github PK

View Code? Open in Web Editor NEW
222.0 5.0 19.0 26.27 MB

Virtual/infinite scroll for Angular

Home Page: https://dhilt.github.io/ngx-ui-scroll/

License: MIT License

TypeScript 98.71% JavaScript 1.16% CSS 0.11% Shell 0.02%
angular virtual-scroll infinite-scroll scrolling scroll virtual-list virtual-scroller virtual-scrolling vscroll

ngx-ui-scroll's Introduction

ngx-ui-scroll CI npm version

ngx-ui-scroll

A directive for Angular framework to provide unlimited bidirectional virtual scrolling over limited viewport. Built on top of vscroll native virtual scrolling engine. Demo is available at dhilt.github.io/ngx-ui-scroll.

can donate? go here 👉
make open-source world better


Compatibility

The ngx-ui-scroll library has no breaking changes in its API, but there are inevitable changes in how it is built and distributed to the host app depending on the version of the Angular.

ngx-ui-scroll Angular compiled support notes
v1 5-12 View Engine no no dependencies (vscroll is not extracted)
v2 5-12 View Engine maintenance vscroll is a bundle-dependency
v3 12+ Ivy active vscroll is a peer-dependency

So if the consumer app is view-engine compatible, you should use ngx-ui-scroll v2 which is in maintenance mode and under v2-legacy branch.

Motivation

Scrolling large datasets may cause performance issues. Many DOM elements, many data-bindings, many event listeners... The common way to improve the performance is to render only a small portion of the dataset visible to a user. Other dataset elements that are not visible to a user are virtualized with upward and downward empty padding elements which should provide a consistent viewport with consistent scrollbar parameters.

The ngx-ui-scroll library provides the *uiScroll structural directive that works like *ngFor and renders a templated element once per item from a collection. By requesting the external Datasource (the implementation of which is a developer responsibility) the *uiScroll directive fetches necessary portion of the dataset and renders corresponded elements until the visible part of the viewport is filled out. It starts to retrieve new data to render new elements again if a user scrolls to the edge of visible element list. It dynamically destroys elements as they become invisible and recreates them if they become visible again.

Features

  • unlimited bidirectional virtual scroll
  • lots of virtualization settings
  • super easy templating
  • infinite mode, demo
  • horizontal mode, demo
  • entire window scrollable, demo
  • items with non-constant heights, demo
  • API Adapter object to manipulate and assess the Scroller, demos

Getting

The *uiScroll directive is a part of UiScrollModule which is available via npm –

npm install ngx-ui-scroll

The UiScrollModule has to be imported in the App/feature module where it is going to be used.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { UiScrollModule } from 'ngx-ui-scroll';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [
    BrowserModule,
    UiScrollModule
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

Usage

Basic usage template may look like

<div class="viewport">
  <div *uiScroll="let item of datasource">
    <b>{{item.text}}</b>
  </div>
</div>

where the viewport is a scrollable area of finite height:

.viewport {
    height: 300px;
    overflow-y: auto;
}

If the height of the viewport is not constrained, it will pull the entire content of the datasource and no scrollbar will appear.

*uiScroll acts like *ngFor in its simplest form, where the datasource is an object of special type (IDatasource), which implements the get method used by the *uiScroll directive to access data by index and count parameters. The directive calls the Datasource.get method each time the user scrolls the list of visible elements to the edge.

import { IDatasource } from 'ngx-ui-scroll';

@Component({ ... })
export class AppComponent {
  datasource: IDatasource = {
    get: (index, count, success) => {
      const data = [];
      for (let i = index; i <= index + count - 1; i++) {
        data.push({ text: 'item #' + i });
      }
      success(data);
    }
  };
}

Datasource.get method must provide an array of count data-items started from index position. If there are no items within given range [index; index + count - 1], an empty array has to be passed. Empty result (or result which length is less than count) is being treated as the edge of the dataset (eof/bof), and no further requests for preceding/tailing items will be issued.

Datasource.get has 3 signatures: callback based, Promise based and Observable based. So, if we want some remote API to be a source of our data, basically it may look like

  datasource: IDatasource = {
    get: (index, count) =>
      this.http.get(`${myApiUrl}?index=${index}&count=${count}`)
  };

More details could be found on the Datasource demo page.

Settings

Datasource implementation along with get method property may include settings object property:

  datasource: IDatasource = {
    get: ...,
    settings: {
      minIndex: 0,
      startIndex: 0,
      ...
    }
  };

Settings are being applied during the Scroller initialization and have an impact on how the Scroller behaves. Below is the list of available settings with descriptions, defaults, types and demos.

Name Type Default Description
bufferSize number,
integer
5 Fixes minimal size of the pack of the datasource items to be requested per single Datasource.get call. Can't be less than 1.
padding number,
float
0.5 Determines the viewport outlets containing real but not visible items. The value is relative to the viewport's size. For example, 0.25 means that there will be as many items at a moment as needed to fill out 100% of the visible part of the viewport, + 25% of the viewport size in the backward direction and + 25% in the forward direction. The value can't be less than 0.01.
startIndex number,
integer
1 Specifies item index to be requested/rendered first. Can be any, but the real datasource boundaries should be taken into account.
minIndex number,
integer
-Infinity Fixes absolute minimal index of the dataset. The datasource left boundary.
maxIndex number,
integer
+Infinity Fixes absolute maximal index of the dataset. The datasource right boundary.
infinite boolean false Enables "infinite" mode, when items rendered once are never removed.
horizontal boolean false Enables "horizontal" mode, when the viewport's orientation is horizontal.
sizeStrategy string enum, 'average' | 'frequent' | 'constant' 'average' Defines how the default item size is calculated. If item has never been rendered, its size is assumed to be the default size: an average or most frequent among all items that have been rendered before, or constant. This has an impact on the process of virtualization.
windowViewport boolean false Enables "entire window scrollable" mode, when the entire window becomes the scrollable viewport.

Adapter API

The Scroller has API to assess its parameters and provide some manipulations at runtime. This API is available via special Adapter object. The datasource needs to be instantiated via operator "new" for the Adapter object to be added to it:

import { Datasource } from 'ngx-ui-scroll';
...
  datasource = new Datasource({
    get: ... ,
    settings: { ... }
  });

Then this.datasource.adapter.packageInfo, this.datasource.adapter.reload() and other Adapter expressions become available. For better typing, it is recommended to specify the Datasource Item type as follows:

import { Datasource } from 'ngx-ui-scroll';
...
  datasource = new Datasource<MyItem>({
    get: ... ,
    settings: { ... }
  });

MyItem should reflect the structure of items that the Datasource will deal with. It is "unknown" by default, and if not set, for example, this.datasource.adapter.firstVisible.data.id expression will produce typescript error: Object is of type 'unknown'. There are some Adapter props and methods dealing with MyItem, and if used, MyItem should be specified.

Below is the list of read-only properties of the Adapter API with descriptions and links to demos.

Name Type Description
packageInfo IPackages {
  consumer: IPackage;
  core: IPackage;
}

IPackage {
  name: string;
  version: string
}
Information about versions of the library ant its core. For example: "ngx-ui-scroll" v3.1.0 (consumer), "vscroll" v1.5.5 (core).
init boolean Indicates whether the Scroller is initialized ot not.
init$ Subject<boolean> An Observable version of "init" property.
isLoading boolean Indicates whether the Scroller is working ot not.
isLoading$ Subject<boolean> An Observable version of "isLoading" property.
itemsCount number A number of items that are rendered in the viewport at a moment.
bufferInfo IBufferInfo {
  firstIndex: number;
  lastIndex: number;
  minIndex: number;
  maxIndex: number;
  absMinIndex: number;
  absMaxIndex: number;
}
  • firstIndex & lastIndex are the first and the last indexes in the current Buffer.
  • minIndex & maxIndex are min and max indexes that were present in the Buffer.
  • absMinIndex & absMaxIndex are min and max indexes that can be present in the Buffer.
  • bof boolean Indicates whether the beginning of the dataset is reached or not.
    bof$ Subject<boolean> An Observable version of "bof" property.
    eof boolean Indicates whether the end of the dataset is reached or not.
    eof$ Subject<boolean> An Observable version of "eof" property.
    firstVisible ItemAdapter<MyItem> {
      $index: number;
      data: MyItem;
      element?: HTMLElement;
    }
    Object of ItemAdapter type containing information about first visible item, where "$index" corresponds to the Datasource item index value, "data" is exactly the item's content passed via Datasource, "element" is a link to DOM element which is relevant to the item.
    firstVisible$ BehaviorSubject
    <ItemAdapter<MyItem>>
    An observable version of "firstVisible" property.
    lastVisible ItemAdapter<MyItem> {
      $index: number;
      data: MyItem;
      element?: HTMLElement;
    }
    Object of ItemAdapter type containing information about last visible item.
    lastVisible$ BehaviorSubject
    <ItemAdapter<MyItem>>
    An observable version of "lastVisible" property.
    paused boolean Indicates whether the Scroller is paused ot not.
    paused$ Subject<boolean> An Observable version of "paused" property.

    Below is the list of invocable methods of the Adapter API with description and links to demos.

    Name Parameters Description
    relax (callback?: Function) Resolves asynchronously when there are no pending processes. If the callback is set, it will be executed right before resolving. Basically, it needs to protect with the relax every piece of the App logic, that might be sensitive to the internal processes of the Scroller, to avoid interference and race conditions. Also, every Adapter method returns the same promise as the relax method, so for example, explicitly waiting for the async result of the append method is equivalent to waiting for the async result of the relax method right after synchronous calling the append method.
    reload (startIndex?: number) Resets the items buffer, resets the viewport params and starts fetching items from startIndex (if set).
    reset (datasource?: IDatasource) Performs hard reset of the Scroller's internal state by re-instantiating all its entities (instead of reusing them when reload). If datasource argument is passed, it will be treated as new Datasource. All props of the datasource are optional and the result Datasource will be a combination (merge) of the original one and the one passed as an argument.
    pause Pauses the Scroller, so the scroll events are not processed by the engine. Also, when paused, the Adapter methods do nothing but resolve immediately without affecting UI (except Adapter.resume and Adapter.reset).
    resume Resumes the Scroller if it was paused.
    check Checks if any of current items changed it's size and runs a procedure to provide internal consistency and new items fetching if needed.
    clip (options: {
      forwardOnly?: boolean,
      backwardOnly?: boolean
    })
    Removes out-of-viewport items on demand. The direction in which invisible items should be clipped can be specified by passing an options object. If no options is passed (or both properties are set to true), clipping will occur in both directions.
    append (options: {
      items: MyItem[],
      eof?: boolean
      decrease?: boolean
    })
    Adds items to the end of the Scroller's buffer/dataset. If eof flag is not set, items will be inserted right after the last buffered item and rendered immediately. If eof is true, rendering will occur only if the right border of the buffer matches the right border of the dataset (end-of-file is reached); otherwise, items will be virtualized as appended to the end of the dataset. Indexes increase by default. If decrease is set to true, indexes are decremented. See also bof/eof.
    prepend (options: {
      items: MyItem[],
      bof?: boolean
      increase?: boolean
    })
    Adds items to the beginning of the Scroller's buffer/dataset. If bof flag is not set, items will be inserted right before the first buffered item and rendered immediately. If bof is true, rendering will occur only if the left border of the buffer matches the left border of the dataset (begin-of-file is reached); otherwise, items will be virtualized as prepended to the beginning of the dataset. Indexes decrease by default. If increase is set to true, indexes are incremented. Note, by historical reasons, items are being reversed during prepending, so if you need to have "initial" order, you may reverse the items array before prepend, or use Adapter.insert API instead. See also bof/eof.
    insert (options: {
      items: MyItem[],
      before?: ItemsPredicate,
      after?: ItemsPredicate,
      beforeIndex?: number,
      afterIndex?: number,
      decrease?: boolean
    })
    Inserts items into the buffer or virtually. Only one of the before, after, beforeIndex and afterIndex options is allowed. If before or after option is used, the Scroller will try to insert items before or after the item that presents in the buffer and satisfies the predicate condition. If beforeIndex or afterIndex option is used, the Scroller will try to insert items by index. If the index to insert is out of the buffer but still belongs to the known datasource boundaries, then the items will be virtualized. Indexes increase by default. Decreasing strategy can be enabled via decrease option.
    remove (options: {
      predicate?: ItemsPredicate,
      indexes?: number[],
      increase?: boolean
    })

    type ItemsPredicate =
      (item: ItemAdapter) =>
        boolean
    Removes items form buffer and/or virtually. Predicate is a function to be applied to every item presently in the buffer. Predicate must return a boolean value. If predicate's return value is true, the item will be removed. Alternatively, if indexes array is passed, the items whose indexes match the list will be removed. Only one of the predicate and indexes options is allowed. In case of indexes, the deletion is performed also virtually. By default, indexes of the items following the deleted ones are decremented. Instead, if increase is set to true, the indexes of the items before the removed ones are incremented.
    replace (options: {
      predicate: ItemsPredicate,
      items: MyItem[],
      fixRight?: boolean
    })
    Replaces items that continuously match the predicate with an array of new items. Indexes are maintained on the assumption that the left border of the dataset is fixed. To release the left border and fix the right one the fixRight option should be set to true.
    update (options: {
      predicate: BufferUpdater,
      fixRight?: boolean
    })

    type BufferUpdater =
      (item: ItemAdapter) =>
        unknown
    Updates existing items by running the predicate function over the Scroller's buffer. The return value of the predicate determines the operation: falsy or empty array to remove, truthy or array with only 1 current item to keep unchanged, non-empty array to replace/insert. Indexes are maintained on the assumption that the left border of the dataset is fixed. To release the left border and fix the right one the fixRight option should be set to true.

    Along with the documented API there are some undocumented features that can be treated as experimental. They are not tested enough and might change over time. Some of them can be found on the experimental tab of the demo app.

    All of the Adapter methods are asynchronous, because they work with DOM and may take time to complete. For this purpose the Adapter methods return a Promise resolving at the moment when the Scroller terminates its internal processes, which were triggered by the invocation of the correspondent Adapter method. This is called the Adapter Return API. This promise has exactly the same nature as the promise of the Adapter.relax method. Both "Relax" and "Return API" are the instruments of the App-Scroller processes normalization. It might be quite important to run some logic after the Scroller finishes its job and relaxes. Below is an example of how an explicit sequence of the Adapter methods can be safely implemented:

    const { adapter } = this.datasource;
    const predicate = ({ $index }) => $index === indexToReplace;
    await adapter.relax();
    await adapter.remove({ predicate });
    await adapter.insert({ items: [itemToReplace], before: predicate });
    console.log('Two-phase replacement done');

    For more information, see Adapter demo page.

    Development

    There are some npm scripts available from package.json:

    • npm start to run demo App on port 4200
    • npm test to run Karma tests
    • npm run build:lib to build the ngx-ui-scroll module into the ./dist/scroller folder
    • npm run build:demo to build the demo App into the ./dist/demo folder

    Along with settings object the datasource implementation may include also devSettings object:

    import { Datasource } from 'ngx-ui-scroll';
    ...
      datasource = new Datasource({
        get: ... ,
        settings: { ... },
        devSettings: {
          debug: true,
          immediateLog: true,
          ...
        }
      });

    The development settings are not documented. Information about it can be taken directly from the source code. The Scroller has "debug" mode with powerful logging which can be enabled via devSettings.debug = true, see Dev Log doc.

    Below is the quick guide for vscroll/ngx-ui-scroll integrated development (this is relevant since ngx-ui-scroll v2 depends on vscroll):

    • clone both ngx-ui-scroll and vscroll repositories into the same folder
    • replace "vscroll" import with local sources here and here.

    Also, there are some environment variables for additional customization of the dev process. In accordance with dotenv approach, the .env file should be placed in the root folder, and it may contain the following variables.

    Name Value Description
    DEV_SERVER_PORT 4200 Port the dev server (webpack) will use. Need to run npm run start:env instead of npm run to make this setting work.
    TEST_BROWSER default | chrome | firefox Platform for running tests. By default a headless chrome is used; "chrome" or "firefox" are for running tests in real (chrome/ff) browser
    TEST_SERVER_PORT 9876 Port that will be used by non-default testing browser

    Any support and participation are welcome, so feel free to donate, submit new Issues and open Pull Requests.


    2024 © dhilt

    ngx-ui-scroll's People

    Contributors

    arturovt avatar chrsadk avatar dependabot[bot] avatar dhilt avatar dyuvzhenko avatar exocomp avatar

    Stargazers

     avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

    Watchers

     avatar  avatar  avatar  avatar  avatar

    ngx-ui-scroll's Issues

    IE11

    Hello,

    The library works great for my usecase in Chrome, Firefox, Edge and Opera (haven't tried Safari yet).

    But it fails in IE11.

    I tried opening your demo page in IE11, and it fails as well. Maybe I'm overlooking something?

    Is the intention to support IE11?

    Best regards
    Christian

    Tests, basic specs

    initialization spec

    • initializing (host component, datasource, viewport, buffer elements)
    • bad datasource
    • settings default (datasource with and without settings; settings overriding)
    • bad settings

    initial load spec

    • initial load with no clip (3 cases)
    • initial load with clip (3-5 cases)
    • infinite mode (based on previous clip-tests but only 1 case)

    scrolling spec

    • single one-direction scroll event (3 cases of 1 scroll event per each direction)
    • mass one-direction scroll events (3 cases of 3-5 scroll events per each direction)
    • mass bouncing scroll events (3 cases of 3-5 sequences of (fwd + bwd) events)
    • mass two-direction scroll events (2) (3 cases of (3-5 fwd + 3-5 bwd) events)

    First documentation requirements

    Need to add usage requirements to the documentation.

    1. Module requirements

    • UiScrollModule importing

    2. Host Component class requirements

    • public property of Datasource type
    • an agreement on Datasource.get and Datasource.settings

    3. Host Component template requirements

    • Viewport wrapper (see "CSS Viewport requirements")
    • *uiScroll syntax
    • items templating

    4. CSS Viewport requirements

    Review scrollbar calculations

    Currently ui-scroll makes scrollbar calculations via getBoundingClientRect. Need to investigate possible issues and review viewport DOM-specific logic if necessary.

    Moment vulnerability alert

    We found a potential security vulnerability in one of your dependencies.
    A dependency defined in ./package-lock.json has known security vulnerabilities and should be updated.

    Need to investigate package-lock.json and find a solution, update exact dependency.

    can we add checboxes

    because the DOM elements are replacing while we scroll...im loading the data from api on every scroll so is it possible to add checkboxes to the table and select multiple rows and show the selected rows??

    current index

    Is it possible to know the current index (first visible) ?
    This would be useful to be able to do a reload at the same positions (for ex. after deleting an element)

    *uiScroll on table row

    Hi @dhilt ,

    was wondering if there is a workaround on using directive on table instead of div. Something like :

    <tbody class="viewport" [style.height.px]="800" *ngIf="datasource">
            <tr *uiScroll="let rows of datasource">
                <td *ngFor="let column of objectKeys(rows)">{{rows[column]}}</td>
            </tr>
    </tbody>
    

    Currently it's not working properly as it wraps each record in <div data-sid="XYZ">

    screen shot 2018-05-14 at 3 29 57 pm

    This would be really awesome if it could work with tables 😄

    Cheers!

    Question on using observables

    Hello,
    I have the following pattern for information but I am not getting how the scroll fetches new values. In my system I retrieve information as such:

    • http GET request fetches all the data
    • The data is then passed to a subject like so
    private nodes: Node[] = []
    private nodesSource = new Subject<any>();
    nodes$ = this.nodesSource.asObservable()
    
    
    constructor(private http: HttpClient ){
        this.http.get(APIroot + '/all').subscribe((data: QUESTIONS.Widget[]) => {
            var temp = []
            for(var entry of data){
                temp.push(new Node(1, data.id))
            }
            this.nodes = temp;
            this.nodesSource.next(data);
        })
    }
    
    search(string){
        var filter = []
        for(var node of this.nodes){
            if(StringMatch(node, string)){
                filter.push(node)
            }
        }
        this.nodesSource.next(filter);
    }
    

    In a component I pass the observable as follows:

      nodes: Node[] = [];
    
      public datasource: IDatasource = {
        get: (index, count) => this.service.nodes$ // from the space above imported to the component
        ,
        devSettings: {
          debug: true
        }
      }
    

    However when I try using my search function, it will only update on the first update. After that it never updates again. I am not understanding why, I would also like to know how I could use index and count with my observable, I do not know how to index an observable.

    Negative index issue

    Thanks for module, it's been exactly what I was looking for. One issues that I'm having:

    • I would like to prevent triggering scroll event when the index goes to negative, basically I dont want to go into loops

    I'm using v0.0.4-rc.1

    isLoading api surface

    Coming in from another issue. In my case I like call back style. But observables are fine too. basically need to trigger a function to scroll down once data is loaded. Come to think of this would also be nice and convenient to work with.

    <div *uiScroll="let item of datasource" onLoad="onLoadFunc">
        <b>{{item.text}}</b>
    </div>
    

    Horizontal scroll not scrolling

    I am working on getting horizontal scroll implemented in a project. I have followed the demo page but I am unable to get the example working in my own project. It appears that the display: inline-block does not apply to the child divs inside each element so they simply stack on each other. To verify that CSS is not the issue, I have included the rendered code by copying the outer HTML from the browser inspector, and it creates a horizontal scroll as shown in the demo.

    I have created a demo stackblitz demonstrating the above here: https://stackblitz.com/edit/angular-ge7otc

    Any ideas are much appreciated.

    Thanks!

    Issue during integration Module not found

    Hey,
    I am using this for my feed screen list as suggested by @dhilt, But after integrating I got this error. `ERROR in ./node_modules/ngx-ui-scroll/esm5/ngx-ui-scroll.js
    Module not found: Error: Can't resolve 'lodash.throttle' in 'D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5'
    resolve 'lodash.throttle' in 'D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5'
    Parsed request is a module
    using description file: D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\package.json (relative path: ./esm5)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\package.json (relative path: ./esm5)
    resolve as module
    D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\main\pwa\node_modules\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\main\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\node_modules doesn't exist or is not a directory
    D:\node_modules doesn't exist or is not a directory
    looking for modules in D:\PlownsWeb\src\main\pwa\node_modules
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    looking for modules in D:\PlownsWeb\src\main\pwa\node_modules
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    looking for modules in D:\PlownsWeb\src\main\pwa\src
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    looking for modules in D:\PlownsWeb\src\main\pwa\src
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    [D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5\node_modules]
    [D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\node_modules]
    [D:\PlownsWeb\src\main\pwa\node_modules\node_modules]
    [D:\PlownsWeb\src\main\node_modules]
    [D:\PlownsWeb\src\node_modules]
    [D:\PlownsWeb\node_modules]
    [D:\node_modules]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    @ ./node_modules/ngx-ui-scroll/esm5/ngx-ui-scroll.js 784:15-41
    @ ./src/app/shared.module.ts
    @ ./src/app/app.module.ts
    @ ./src/main.ts
    @ multi webpack-dev-server/client?http://0.0.0.0:0 ./src/main.ts
    ERROR in D:/PlownsWeb/src/main/pwa/node_modules/ngx-ui-scroll/src/component/interfaces/direction.d.ts (2,15): In ambient enum decl
    arations member initializer must be constant expression.
    ERROR in D:/PlownsWeb/src/main/pwa/node_modules/ngx-ui-scroll/src/component/interfaces/direction.d.ts (3,16): In ambient enum decl
    arations member initializer must be constant expression.
    ERROR in Error: Metadata version mismatch for module D:/PlownsWeb/src/main/pwa/node_modules/ngx-ui-scroll/ngx-ui-scroll.d.ts, foun
    d version 4, expected 3, resolving symbol SharedModule in D:/PlownsWeb/src/main/pwa/src/app/shared.module.ts, resolving symbol Sha
    redModule in D:/PlownsWeb/src/main/pwa/src/app/shared.module.ts
    at syntaxError (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:1729:34)
    at simplifyInContext (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:24979:23)
    at StaticReflector.simplify (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:24991:13)
    at StaticReflector.annotations (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:24418:41)
    at _getNgModuleMetadata (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:138:31)
    at _extractLazyRoutesFromStaticModule (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:109:26
    )
    at D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:129:27
    at Array.reduce ()
    at extractLazyRoutesFromStaticModule (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:128:10
    )
    at Object.listLazyRoutesOfModule (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:53:22)
    at Function.NgTools_InternalApi_NG_2.listLazyRoutes (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools

    api.js:91:39)
    at AotPlugin._getLazyRoutesFromNgtools (D:\PlownsWeb\src\main\pwa\node_modules@ngtools\webpack\src\plugin.js:241:66)
    at _donePromise.Promise.resolve.then.then.then.then.then (D:\PlownsWeb\src\main\pwa\node_modules@ngtools\webpack\src\plugin.j
    s:495:24)
    at
    at process._tickCallback (internal/process/next_tick.js:118:7)

    webpack: Failed to compile.
    ^CTerminate batch job (Y/N)? y

    D:\PlownsWeb\src\main\pwa>ng serve
    ** NG Live Development Server is listening on localhost:4200, open your browser on http://localhost:4200/ **
    Date: 2018-03-27T04:54:46.836Z
    Hash: 070901e42f20166c02d1
    Time: 28169ms
    chunk {inline} inline.bundle.js (inline) 5.79 kB [entry] [rendered]
    chunk {main} main.bundle.js (main) 2.67 MB [initial] [rendered]
    chunk {polyfills} polyfills.bundle.js (polyfills) 1.3 MB [initial] [rendered]
    chunk {styles} styles.bundle.js (styles) 295 kB [initial] [rendered]
    chunk {vendor} vendor.bundle.js (vendor) 18 MB [initial] [rendered]

    ERROR in ./node_modules/ngx-ui-scroll/esm5/ngx-ui-scroll.js
    Module not found: Error: Can't resolve 'lodash.throttle' in 'D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5'
    resolve 'lodash.throttle' in 'D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5'
    Parsed request is a module
    using description file: D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\package.json (relative path: ./esm5)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\package.json (relative path: ./esm5)
    resolve as module
    D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\main\pwa\node_modules\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\main\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\src\node_modules doesn't exist or is not a directory
    D:\PlownsWeb\node_modules doesn't exist or is not a directory
    D:\node_modules doesn't exist or is not a directory
    looking for modules in D:\PlownsWeb\src\main\pwa\node_modules
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    looking for modules in D:\PlownsWeb\src\main\pwa\node_modules
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./node_modules/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle doesn't exist
    looking for modules in D:\PlownsWeb\src\main\pwa\src
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    looking for modules in D:\PlownsWeb\src\main\pwa\src
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    Field 'browser' doesn't contain a valid alias configuration
    after using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src)
    using description file: D:\PlownsWeb\src\main\pwa\package.json (relative path: ./src/lodash.throttle)
    no extension
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    .ts
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts doesn't exist
    .js
    Field 'browser' doesn't contain a valid alias configuration
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js doesn't exist
    as directory
    D:\PlownsWeb\src\main\pwa\src\lodash.throttle doesn't exist
    [D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\esm5\node_modules]
    [D:\PlownsWeb\src\main\pwa\node_modules\ngx-ui-scroll\node_modules]
    [D:\PlownsWeb\src\main\pwa\node_modules\node_modules]
    [D:\PlownsWeb\src\main\node_modules]
    [D:\PlownsWeb\src\node_modules]
    [D:\PlownsWeb\node_modules]
    [D:\node_modules]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\node_modules\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.ts]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle.js]
    [D:\PlownsWeb\src\main\pwa\src\lodash.throttle]
    @ ./node_modules/ngx-ui-scroll/esm5/ngx-ui-scroll.js 784:15-41
    @ ./src/app/shared.module.ts
    @ ./src/app/app.module.ts
    @ ./src/main.ts
    @ multi webpack-dev-server/client?http://0.0.0.0:0 ./src/main.ts
    ERROR in D:/PlownsWeb/src/main/pwa/node_modules/ngx-ui-scroll/src/component/interfaces/direction.d.ts (2,15): In ambient enum decl
    arations member initializer must be constant expression.
    ERROR in D:/PlownsWeb/src/main/pwa/node_modules/ngx-ui-scroll/src/component/interfaces/direction.d.ts (3,16): In ambient enum decl
    arations member initializer must be constant expression.
    ERROR in Error: Metadata version mismatch for module D:/PlownsWeb/src/main/pwa/node_modules/ngx-ui-scroll/ngx-ui-scroll.d.ts, foun
    d version 4, expected 3, resolving symbol SharedModule in D:/PlownsWeb/src/main/pwa/src/app/shared.module.ts, resolving symbol Sha
    redModule in D:/PlownsWeb/src/main/pwa/src/app/shared.module.ts
    at syntaxError (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:1729:34)
    at simplifyInContext (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:24979:23)
    at StaticReflector.simplify (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:24991:13)
    at StaticReflector.annotations (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler\bundles\compiler.umd.js:24418:41)
    at _getNgModuleMetadata (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:138:31)
    at _extractLazyRoutesFromStaticModule (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:109:26
    )
    at D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:129:27
    at Array.reduce ()
    at extractLazyRoutesFromStaticModule (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:128:10
    )
    at Object.listLazyRoutesOfModule (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools_impl.js:53:22)
    at Function.NgTools_InternalApi_NG_2.listLazyRoutes (D:\PlownsWeb\src\main\pwa\node_modules@angular\compiler-cli\src\ngtools

    api.js:91:39)
    at AotPlugin._getLazyRoutesFromNgtools (D:\PlownsWeb\src\main\pwa\node_modules@ngtools\webpack\src\plugin.js:241:66)
    at _donePromise.Promise.resolve.then.then.then.then.then (D:\PlownsWeb\src\main\pwa\node_modules@ngtools\webpack\src\plugin.j
    s:495:24)
    at
    at process._tickCallback (internal/process/next_tick.js:118:7)

    webpack: Failed to compile.`

    Deployment

    Travis? It should include build and tests running.

    Inverted datasource logic

    How can i start the scroll on bottom?
    I have items with diffrent height (chat app with messages / images / video etc...)
    And why on the page init the datasource run the get function twice?
    I set buffer size to 20

    Clear the datasource. API method to reload the scroller

    I tried to use the scroll with a datasource that is the result of a search, but I can not find a way to tell the scroll component that the datasource has changed in content, so it only triggers the get method first time.

    I have tried setting my datasource to null and then create a new one after a new search, and also tried to put an *ngIf on the parent div to disable and re-enable it again but still the scroll does not care if my datasource has changed.

    Is there a way I can clear the datasource?

    list entities count

    Is there any way to get a number of entities currently being displayed on screen?

    Window scroll

    Hey @dhilt,

    I can't seem to figure out how to make it work with window scroll.
    I don't see anything on the documentation or on the examples but I know that on the AngularJS version it was supported so probably is it something that will be supported in the near future?

    Concept

    Здесь можно обсуждать все идеи и моменты, касающиеся продукта до выхода первой версии. Что и как работает, улучшения, возможные направления развития.

    With `maxIndex` setting first get call has count 1

    I'm optionally only allowing scrolling up and using the newly added setting maxIndex as

    maxIndex: this.allowDown ? +Infinity : 0

    But the result is that the first get call has a count value of only 1 instead of the bufferSize.

    In version 0.0.7 I could achieve this by calling success with an empty array and returning form the get callback for a 'down' call, but this now prevents any data load.

    Horizontal scrolling

    Need to implement horizontal scrolling. Proposal:

    Settings.horizontal = true/false
    

    Virtual scrolling with infinite scrolling/pagination?

    Is there a way to support paginated data sets with this directive so that I can virtually scroll through an infinite scrolling list by updating my datasource (think async binding via observable) until the user has loaded all the data?

    We do this with some data grids elsewhere by using the count/index to slice the data source being fed to the observable. It's handy because it reduces the datasource to approximately the buffer size yielding great performance. However, if one has to load a huge data set to do this, it becomes ineffective. If we could specific a total records setting that gave this directive a way to calculate scroller handle position and 'waypoints' where an event was dispatched every time the scroller reached x% of the current buffer, we could really leverage this nicely.

    Add blank rows while fetching new items

    Would it be possible to add blank rows of expected quantity (before dispatching the request) instead of increasing the gap in top or bottom part of the list when scrolling?
    It's really annoying to see the blank space while waiting for the data to be loaded, if the above was possible, we could show blank rows (with a spinner for example) and once the data are loaded we can then populate the pre-generated rows with the loaded data.

    What do you think?

    TypeError: Cannot read property 'getBoundingClientRect' of undefined

    Hi @dhilt ,

    I'm getting and error at some point when reloading the list:

    ERROR TypeError: Cannot read property 'getBoundingClientRect' of undefined
        at Routines.getParams (ngx-ui-scroll.js:284)
        at Item.getParams (ngx-ui-scroll.js:1542)
        at Cache.add (ngx-ui-scroll.js:623)
        at eval (ngx-ui-scroll.js:684)
        at Array.forEach (<anonymous>)
        at Buffer.reset (ngx-ui-scroll.js:683)
        at Scroller.reload (ngx-ui-scroll.js:1233)
        at Workflow.resolveAdapter (ngx-ui-scroll.js:2098)
        at SafeSubscriber.__tryOrUnsub (Subscriber.js:243)
        at SafeSubscriber.next (Subscriber.js:190)
    

    This happens when previous list had more items then the new one... it's quite strange cause I cant catch it every time.

    Routines.prototype.getParams = /**
         * @param {?} element
         * @return {?}
         */
        function (element) {
            return element.getBoundingClientRect();
        };
    

    element is undefined for one item, not sure why, and it brakes.

    Empty space buildup at the top when row item change height

    Is there a way to refresh the scroll bars when the items change height as I noticed in my use of the component that when the row items change height after the view is rendering scrolling with the new items now causes empty space at the top of the list.

    How can scroll on one direction?

    After implementing this I got another issue. when I scroll to top data source index is started going negative. I just want it to scroll in positive index. My Data source code is :

    datasource: Datasource = {
        get: (index, count) => {
          if (index < 0) {
            return Observable.of([]);
          }
          return this.feedsService.getLatestFeeds(this.cursor, false, count).flatMap(value => {
            console.log(index + '    ' + count);
            this.cursor = value.curs;
            console.log(value.matches);
            return Observable.of(value.matches);
          });
        },
        settings: {
          bufferSize: 20
        }
      }
    

    Feature request minIndex setting

    As a common use case involves the limitation of the index in order to call an api I suggest implementing a setting which limits the index from which data gets loaded.

    datasource: IDatasource = {
      get: (index, count, success) => {
        const data = [];
        for (let i = index; i <= index + count - 1; i++) {
          data.push({ id: i, text: 'item #' + i });
        }
        success(data);
      },
      settings: {
        minIndex: 0 // would be nice to have ;)
      }
    }
    

    In this example get would only be called with index >= 0 which avoids checks like:

    get: (index, count, success) => {
      const start = Math.max(index, 0); // no negative indexes 
      const data = [];
        for (let i = index; i <= index + count - 1; i++) {
          data.push({ id: i, text: 'item #' + i });
        }
      success(data);
    }
    

    Adapter.append method

    Need to implement Adapter.append method to be able to add items to the end of the scroller' buffer on-flight.

    perfect scrollbar look

    I have a question: can ngx-ui-scroll be used toghether with a perfect scrollbal (like ngx-perfect-scrollbar), or the concepts are not compatible?

    Actually I am more interested to replace the native scroll used in ngx-ui-scroll with a perfect scrollbar look.

    I really do not know if I am asking you for a new feature, or I can do this on top of ngx-ui-scroll just with css.

    Module

    The UiScrollDirective needs an own Module.

    Security vulnerability in hapijs / hoek 2.16.3, Angular CLI dependency

    hapijs / hoek Known security vulnerability in 2.16.3

    Details here.

    Is blocked by angular/angular-cli#10480.

    virtual scrolling on sub groups

    @dhilt I have weird requirement now. I created new stackblitz. Now I need to implement virtual scrolling for sub groups because there is requirement to implement to display detailed view for each item in the group. And with each group having like items up to 100, rendering entire group is still causing performance issues for me and I am trying to figure out the way to implement virtual scrolling to render only limited no of items from group which are visible in UI. Is there any way we can achieve. Would appreciate any thoughts

    Preload

    Is there a possibility to antecipete the load of the itens. I mean, before the scroll reach the top or the bottom, the load is called. My problem is, when the load is called it takes 1-2 seconds to bring and rendenize my itens on html

    Scroll issue on mobile device (Chrome/Android)

    Hello,

    I have tested the "Entire window scrollable" demo on Chrome 68.0.3440.91 on mobile device Huawei Mate 10 Pro using Android 8.0.0.

    https://dhilt.github.io/ngx-ui-scroll/#/window

    It doesn't really allow you to scroll through the items. It stops at some points, and you have to go further up, and then swipe very quick to get a few more rows shown. Sometimes it rapidly jumps to the top.

    I don't know if the component is supposed to support mobile devices, but i hope so :)

    Thanks
    Christian

    Chat app UI use case

    Hello there, I'm just wondering if this plugin fits the bill to create a chat like UI. Like similar to whatsapp etc. I have spent a whole day trying a few other angular based virtual scroll and none of them fit the use case. none of them have variable height *known only during runtime, working properly. some do but the height needs to be determined before hand . And for some the array have to be mutable cannot add to the datasource have to create a new array and re-render which is not good for performance since new messages will come often while the user is chatting. And for chat UI the scroll direction is reversed and it should render from the bottom up. i dont need to worry about remote fetching all the messages will be in an array from localstorage. does this fit the bill?

    Will probably experiment with this too in a few days but maybe I can get strategy or approach or maybe saves me sometime if this does not fit the bill.

    Thank you!

    Better usage

    Think about better usage of things: template, datasource, directive instead of (or over) component.

    weird index when scrolling back

    The index is correctly incremented by the number defined in bufferSize when scrolling down. However when I scroll up, I get weird indexes and I don't know how to calculate current position.

    Please see below the flow. I'm only using some very basic example from your demo pages, just populated with some real data and that's it.

    index: 0
    Scroll down:
    index: 4
    Scroll down:
    index: 8
    Scroll down:
    index: 12
    Scroll up:
    Index: 0 //// why 1???
    Scroll down:
    index: 11 /// ????

    Thanks in advance,
    Alex

    Multiple items per row

    Hi

    I would like to know if this supports multiple items per row, for example when flex-box is used? None of the examples show that it could.

    Recommend Projects

    • React photo React

      A declarative, efficient, and flexible JavaScript library for building user interfaces.

    • Vue.js photo Vue.js

      🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

    • Typescript photo Typescript

      TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

    • TensorFlow photo TensorFlow

      An Open Source Machine Learning Framework for Everyone

    • Django photo Django

      The Web framework for perfectionists with deadlines.

    • D3 photo D3

      Bring data to life with SVG, Canvas and HTML. 📊📈🎉

    Recommend Topics

    • javascript

      JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

    • web

      Some thing interesting about web. New door for the world.

    • server

      A server is a program made to process requests and deliver data to clients.

    • Machine learning

      Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

    • Game

      Some thing interesting about game, make everyone happy.

    Recommend Org

    • Facebook photo Facebook

      We are working to build community through open source technology. NB: members must have two-factor auth.

    • Microsoft photo Microsoft

      Open source projects and samples from Microsoft.

    • Google photo Google

      Google ❤️ Open Source for everyone.

    • D3 photo D3

      Data-Driven Documents codes.