Endless Scroll using Typescript and Angular 4

I'm currently in the process of setting up an angular4 application, pulling data from an API. I'm working on implementing an easy infinite scroll feature, and while it's functioning properly, the initial page content is being loaded twice. How can I prevent this double loading issue? Since the HTML part simply triggers the (scrolled)="onScroll()" function, I have omitted that code snippet. Thank you!

discover.component.ts:

export class DiscoverComponent implements OnInit {
  stories: any;
  resultHits: Array<Object>;
  page:any;
  feed:any;
  hits:string;

  constructor(private storiesService: StoriesService) {}


  ngOnInit() {
  }

  getLatestFeed() {
    this.page = 0;
    this.feed = 'latest';
    this.hits = '6';
    console.log("latest feed");
    this.getFeed(this.page, this.feed, this.hits);
  }

  getCuratedFeed() {
    this.page = 0;
    this.feed = 'curated';
    this.hits = '6';
    this.getFeed(this.page, this.feed, this.hits);
    console.log("curated feed");
  }

  getTrendingFeed() {
    this.page = 0;
    this.feed = 'trending';
    this.hits = '6';
    this.getFeed(this.page, this.feed, this.hits);
    console.log("trending feed");
  }

  onScroll() {
    this.getMore(this.page, this.feed, this.hits);
  }

  //Get the latest feed

  private getFeed(page, feed, hits) {
    this.storiesService.getFeed(this.page, this.feed, this.hits).then((data) => {
      this.stories = data;
      this.stories = this.stories.hits;
      this.resultHits = [];
      for (var i = 0; i < this.stories.length; i++) {
        console.log(this.stories[i])
        if (i < this.stories.length) {
          this.resultHits.push(this.stories[i]);
        }
      }
      console.log(this.stories);
    });
  }

  //Scroll
  private getMore(page, feed, hits) {
    this.storiesService.getFeed(this.page, this.feed, this.hits).then((data) => {
      this.page++;
      this.stories = data;
      this.stories = this.stories.hits;
      for (var i = 0; i < this.stories.length; i++) {
        console.log(this.stories[i])
        if (i < this.stories.length) {
          this.resultHits.push(this.stories[i]);
        }
      }
      console.log(this.stories);
    });
  }
}

stories.component.ts:

export class StoriesService implements OnInit {

  private stories: any;

  constructor(private http: HttpClient) {

  }

  ngOnInit() { }

  //Get 6 latest story feeds
  getFeed(page: any, feed: string, hits: string) {

    let promise = new Promise((resolve, reject) => {
      firebase.auth().currentUser.getIdToken(true).then((idToken) => {
        let headers = new HttpHeaders()
          .set('user_token', idToken);
        let params = new HttpParams()
          .set('page', page)
          .set('feed', feed)
          .set('hits', hits)
        console.log(params);
        this.http.get('https://dev-api.byrd.news/v1/stories', { params, headers })
          .toPromise()
          .then(data => {
            resolve(data);
          })
      }, error => {
        reject(error);
      })
    })
    return promise;
  }

HTML:

<app-top-nav></app-top-nav>


<nav class="navbar navbar-default navbar-fixed-top">
  <div class="container">
    <li class="navbar-right"><a (click)="getCuratedFeed()">Curated</a></li>
    <li class="navbar-right"><a (click)="getTrendingFeed()">Trending</a></li>
    <li class="navbar-right"><a (click)="getLatestFeed()">Latest</a></li>

    <li class="navbar-right"><a routerLink="/map" routerLinkAcive="active">Map</a></li>

  </div>
</nav>

<h1>DiscoverComponent</h1>



<h2> {{feed}} <h2>
<div class="row">
  <div class="col-4 col-md-4 col-sm-12" *ngFor="let story of resultHits">
    <div class="thumbnail">
      <img *ngIf="story.storyMediaType === 'image'" class="img-fluid" src="{{story.storyThumbnailImage}}" />
      <div class="caption">
        <p>{{story.storyCity}}, {{story.storyCountry}}</p>
        <h3>{{story.storyHeadline}}</h3>
        <p>Uploaded {{story.uploadDate}}</p>
        <p>User: {{story.userDisplayName}}</p>
        <p><a href="#" class="btn btn-primary" role="button">Like</a> <a href="#" class="btn btn-default" role="button">Button</a></p>
      </div>
    </div>
  </div>
</div>

<hr>

<div infiniteScroll [infiniteScrollDistance]="2" [infiniteScrollThrottle]="1000" (scrolled)="onScroll()">

</div>

<div class="notification is-warning" *ngIf="finished">
  <p>No more material available!</p>
</div>

Answer №1

You could potentially streamline the code by eliminating redundancies and preventing the scroll function from executing when the page property is set to 0.

export class DiscoverComponent {
    stories: any;
    resultHits: Array<Object>;
    page:any = 0;
    feed:any;
    hits:string;

    constructor(private storiesService: StoriesService) {} 

    getInitialFeed(feed) {
        this.getFeed(0, feed, '6');
        this.page = 1;
    }   

    onScroll() {
        if(this.page > 0) {
            this.getFeed(this.page, this.feed, this.hits);
        }
    }

    private getFeed(page, feed, hits) {
        this.storiesService.getFeed(page, feed, hits).then((data) => {
            this.stories = data;
            this.stories = this.stories.hits;
            this.resultHits = [];
            for (var i = 0; i < this.stories.length; i++) {
                this.resultHits.push(this.stories[i]);            
            }
        });
        if(page > 0) this.page++;
    } 
}

Html:

<li class="navbar-right"><a (click)="getInitialFeed('curated')">Curated</a></li>
<li class="navbar-right"><a (click)="getInitialFeed('trending')">Trending</a></li>
<li class="navbar-right"><a (click)="getInitialFeed('latest')">Latest</a></li>

You may also consider adding a @Hostlistener on the onScrol function like this:

import { Component, HostListener} from "@angular/core";
..
@HostListener("window:scroll")
    onScroll() {
        if(this.page > 0) {
            this.getFeed(this.page, this.feed, this.hits);
        }
    }

Edit: It could be beneficial to prevent the onScroll function from executing while it is already running and not yet finished loading.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having trouble retrieving the return value from an Angular HTTP POST request?

My current project involves developing an Angular frontend that will handle multiple HTTP POST requests. The data is sent to the backend, which then responds with a confirmation. While the first part of the process is working smoothly, I'm encounterin ...

Sending both headers and body in Angular using HttpClientWould you like any further assistance with

When attempting to send user information and a JWT token to my server, I am encountering an issue where the server is printing 'undefined' when I try to access the request body. Below is the Angular code I am using: subscribeToPlan(jwtToken: ...

When using Typescript with React, the importScripts() function may result in the error message: "'importScripts' is not defined no-undef"

As per the instructions from Google Workbox, the initial step advised in serviceWorker.js is: importScripts('https://storage.googleapis.com/workbox-cdn/releases/4.3.1/workbox-sw.js'); However, when attempting to execute npm run start, I encount ...

Calculate the minimum, maximum, and average values within an array containing nested elements

I want to calculate the min, max, and average values for nested data that already have these values precalculated. Essentially, I'm looking for the average of averages, min of min, and max of max. I have a large dataset that includes the min, max, an ...

How to troubleshoot the issue of "Error: (SystemJS) module is not defined" in Angular 2?

I am a beginner in the world of Angular2. It is known that in Angular2, there is a way to reference a file using a relative path by defining moduleId : module.id in the component meta data. However, I have tried doing it this way and keep encountering the ...

Is it possible to turn off Angular CLI ng build linting for a specific directory?

I am facing an issue with a specific directory in my project template that I want to exclude from linting. Despite excluding it in both tsconfig and eslint, running eslint works fine but when using ng build, the directory is still included in linting and e ...

Invoke a public method in TypeScript

I'm a newcomer to typescript. In my node-express application, I am trying to call a public function. However, I keep encountering an issue where this is always undefined, leading to errors whenever I attempt to call the public function. Below is the s ...

Export a TypeScript type dynamically

I'm currently developing an application and I have a query regarding dynamically exporting a type. My API call retrieves a list of categories. const getCategories = async () => { const fetchedCategories = await axios.get(uri) // Expected outp ...

Error encountered during NextJS build - file or directory not found for 500.html

I recently made the switch from Page Router to App router. Transitioning pages - 500.tsx to app - 500 - page.tsx However, I encountered an error when running yarn build/next build: > Build error occurred [Error: ENOENT: no such file or direc ...

Unlock the power of TypeScript's inheritance by utilizing static methods for type

In my TypeScript project, I have two classes: BaseModel and HotelModel. The HotelModel extends the BaseModel class, which provides static methods like findById, all, etc. export default class BaseModel { private collection:string _id:string | undefine ...

Numerous instances of a specific custom directive in Angular2

I'm in the process of developing an Angular application, focusing on creating highly reusable code using directives (as components). <div class="container container-fluid" > <div class="row"> <table class="table table-responsive ...

Type parameter that allows for the retrieval of a function parameter's type based on specific conditions

There is a custom type I've developed to extract the type of the second parameter in a function: type SecondParam<T> = T extends (a: any, b: infer R) => any ? R : never; For the most part, it functions correctly: type T1 = SecondParam& ...

Looking to preview files on a server before downloading them? If you're getting the error message "Not allowed to load local resource: blob,"

Update: To clarify, we are using <embed #reportPdf width="100%" height="800"> and: this.pdf.nativeElement.src = this._window.URL.createObjectURL(this.re); It functions properly on Safari and Firefox. However, when loaded on Chrome, it displays as ...

What is the best way to employ TypeScript for passing parameters to JavaScript functions that utilize the arguments object?

Using Angular 8 at the moment and attempting to implement a script from someone else. However, I am facing an issue due to my lack of knowledge in this area. The function in the javascript operates like this: window.X = function() { var e = argument.l ...

Angular 2 endless iframe loading issue

I'm working on setting up a simple iframe in an Angular 2 project. Check out the code here When I tried using a raw URL in the iframe src, I encountered an error saying unsafe value used in a resource URL context <!-- 1) Error : unsafe value use ...

Incorporating external JavaScript libraries into an Angular application

I'm currently working on an Angular 4 application where I have a JavaScript component named timeline.js. This component functions properly, but I am looking to integrate it into my Angular 4 project. To do this, I placed the js file in the directory a ...

What is the best approach to injecting a service into a class that needs to be created in the app module in Angular 7?

In my current project utilizing ngxs, I am eager to implement the ngxs logger plugin but with a twist - I aim to customize the logger to enable logging to the backend. Despite several attempts, I am struggling to inject my RestService into the logger class ...

Calls to webApi with an Angular disorderly (asynchronous) pattern

Whenever I type in a textbox, it triggers a call to a webapi. The issue is that if I type too quickly, the calls and responses get mixed up. For example, when typing "hello": call with h call with "hel" call with "hello" call with "hell" call with "he" ...

Guide to dynamically loading separate components on a single page in Angular 9

Rendering all components or widgets on the page at once can slow down the application's loading time. I prefer to have app-sidebar1, app-body, and app-sidebar2 load onto the DOM sequentially based on priority, rather than waiting for all components t ...

NGRX: Issue with http retry interceptor preventing failure action from triggering

Incorporating NGRX into my project, I am looking to implement simple GET requests to an API that are retried up to five times. The reason behind this is occasional throttling from Azure Cosmos-DB (free-tier). To achieve this, I have set up an http-interce ...