Home > database >  Fire event at Infinite horizontal scroll end in ionic 5
Fire event at Infinite horizontal scroll end in ionic 5

Time:02-11

I am trying to build infinite scrolling content horizontally. Following code does the job on the first load.

HTML:

  <div >
    <div >
      <div  *ngFor="let user of userList">
        <ion-grid>
          <ion-row>
            {{user.name}}
          </ion-row>
        </ion-grid>
      </div>
    </div>
  </div>

SCSS:

.thumnails{
    overflow-x: scroll;
    overflow-y: hidden;
    .list-thumbnail{
      height: 100%;
      white-space: nowrap;
      .img-thumb{
        display: inline-block;
        border: 1px solid #ddd;
        border-radius: 4px;
        padding: 3px;
      }
    }
  }
  ::-webkit-scrollbar { 
    display: none; 
  }

After this, I need to fire a method when a user reaches the end on scroll. Ionic has the component ion-infinite-scroll which works in vertical scroll but it's not firing when I use it with the above code.

Is there a way to fire an event at the end of the horizontal scroll?

CodePudding user response:

I suggest trying the ionScroll event from ion-content component.

  1. Enable ionScroll like:

    <ion-content [scrollEvents]="true" (ionScroll)="logScrolling($event)">

  2. On logScrolling check to see if the scroll reached a certain point. If it did, add more data to your infinite scrolling content:

    async logScrolling($event) {
       if($event.target.localName != "ion-content") {
          return;
        }
       const scrollElement = await $event.target.getScrollElement();
       const scrollWidth = scrollElement.scrollWidth - scrollElement.clientWidth;
       const threshold = 50;
       if(scrollWidth < threshold) {
          //...load data here
       }}
    

I did not test it but it should work like that. Please let me know if you ran into any problems.

CodePudding user response:

Here is my solution. Is not beautiful and I did not test it for performance issues but it does exactly what you want

HTML:

<ion-content>
  <div  (scroll)="scrollEv($event)">
    <div >
      <div  *ngFor="let user of userList">
        <span  hidden>{{ user.id }}</span>
        <ion-grid>
          <ion-row>
            {{ user.name }}
          </ion-row>
        </ion-grid>
      </div>
    </div>
  </div>
</ion-content>

TS:

  userList: Array<any> = [];
  // elements count till the end of list to trigger the `getData()` function
  elementsToTrigger: number = 10;

  constructor() { }

  ngOnInit() {
    this.getData();
  }

  scrollEv(ev) {
    // get the last visible on screen element of the list by it's coordenates:
    // x => the offsetWidth of the body - 5px so it doesn't get out of boundaries
    // y => distance the list is from the top. Note that here the list is fixed at the top because it's the only element on screen, but if, at some point,
    // it will scroll or be placed at someplace else you should get this distance manually before this next line.
    let elByCoords = document.elementFromPoint(document.body.offsetWidth - 5, 0);
    let elId = elByCoords.children[0].textContent;

    // check if the last element visible on screen is the "elementsToTrigger'th to last" and if so get more data
    // here you should also check if all data has been loaded so you don't keep sending requests to your backend
    if ((this.userList.length - this.userList.findIndex(user => user.id ===  elId)) <= this.elementsToTrigger) {
      this.getData();
    }
  }

  getData() {
    // here goes your logic to retrieve more results from database.
    let startAt: number = this.userList?.length || 0;
    let arr = [];
    for (let i = startAt; i < startAt   50; i  ) {
      arr.push({ id: i, name: `User ${i}` });
    }
    this.userList = (this.userList || []).concat(arr);
  }

You may need to play a little with document.elementFromPoint(x, y) to find the correct values

  • Related