dhilt / ngx-ui-scroll

Virtual/infinite scroll for Angular
https://dhilt.github.io/ngx-ui-scroll/
MIT License
224 stars 18 forks source link

Initialization with an empty array makes 'get' to don't be called #162

Closed Ar-Kan closed 4 years ago

Ar-Kan commented 4 years ago

Hello,

I need to have the scroller initialize without elements, and populate it after a user search input.

My current implementation:

query_made: boolean = false;
model_query: Array<object>;
_items: Array<object> = [];

datasource = new Datasource({
  get: (index, count, success) => {
    if (!this.query_made) {
      success([]);
      return;
    }

    /**make a new request or return existing items */
  },
  settings: {
    padding: 1.5,
    bufferSize: 15, // quantitie
    startIndex: 0
  },
  devSettings: {
    debug: false
  }
});

Then load the first items with append

add_items(items: Array<object>) {
  this.datasource.adapter.append(items);
  this.query_made = true;
}

But when 'datasource' gets the empty array it stops loading dynamically the items and acts as a common list component.

Any help is appreciated, thanks!

dhilt commented 4 years ago

@Ar-Kan Thanks for the question! The point is that if the Datasource returns empty array then BOF or/and EOF is reached and the Scroller remembers it. This is what the doc tells about it:

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.

The first option getting to my mind is just to hide the view with *ngIf="!query_made". Show empty viewport as a separate container instead. And success([]) can be removed from the datasource.get implementation.

Also, Adapter.reload might be helpful if you want to reset EOF/BOF at some moment. I created tiny demo on Stackblitz showing it: angular-ngx-ui-scroll-1-5-0-enable-on-demand. This way the datasource can safely return [], just trigger reload at proper time.

Another option would be to use Adapter.fix({ minIndex, maxIndex }) undocumented method. This way you may set new boundaries of the datasource without reload. Some details can be found in the Adapter.fix PR description, especially in the "Prepeding and virtualizing" chapter. Hacky but powerful.

As a bonus, Adapter.reset method will be available soon (PR is here), it will allow to perform hard reset of the Scroller and replace datasource object with its settings and/or get method.

I want to say that the Datasource is the main thing around which the other ones should dance. You need to maintain carefully EOF/BOF logic, to be in agreement with the Scroller and don't try to trick him. Perhaps you'd better to reconsider the appending approach and shift all related data flow logic to the datasource.get level. I'm not sure about the details, but I believe the Datasource.get should be our king.

DaveLomber commented 4 years ago

Another option that we use is to initialize datasource at the time we have > 0 records

Ar-Kan commented 4 years ago

Ah now I get it, I thought it was something related with BOF/EOF but didn't understand the concept., also the part about giving get a central rol, but now it will work beautifully 😄.

Actually, a little time ago, I was able to get it working, by replacing success([]) with fail(), though I believe it wasn't meant for this specific case.

Thank you @dhilt and @DaveLomber for all the help, much appreciated. Very helpfull indeed.

To finalize, I wish to say that this is an awesome package, I have used others before and none compare, it's really a great job, very well done!