Angular —Simple Infinite scroller directive with RxJS Observables

This post is a follow up on my previous blog post of implementing Naive Infinite scroller with RxJS Observables. In this post we will create an Angular 2 directive to build the infinite scroll feature. We will use the HackerNews Unofficial API to populate our container

I am using angular-cli to scaffold the project.

ng new infinite-scroller-poc --style=scss

Once it generates the project, cd into infinite-scroller-poc

Angular cli provides us with a bunch of commands to generate component, directive, service and module.

We are going to generate a service and a directive.

ng g service hacker-news
ng g directive infinite-scroller

Note: Angular CLI will register the directive to the app.module.ts but will not add the service to the providers array. You have add that in. The app.module.ts should look like below.

Lets add the hacker news api call to our service. Below is hacker-news.service.ts. It has one function getLatestStories.

Time to build our infinite scroller directive. Below is the entire infinite scroller directive and we break it down section by section.

The directive is going to take 3 inputs

  1. scrollPercent — until what percentage the user should scroll the container for the scrollCallback to be called
  2. scrollCallback — callback function which should return an observable
  3. immediateCallback — a boolean value, if true as soon as the directive is initialized call the callback()

Angular provides 4 lifecycle hooks for the component and directive.

Source: angular.io

For our directive, we want to tap into the ngAfterViewInit lifecycle hook to register our scroll events and process them. In constructor, we are injecting the ElementRef which gives us the reference to the element to which the directive is applied. In this case it will be our scroll container.

constructor(private elm: ElementRef) { }
ngAfterViewInit() {
    this.registerScrollEvent();  
    this.streamScrollEvents();
    this.requestCallbackOnScroll();
}

In ngAfterViewInit lifecycle hook, we execute three functions.

  1. registerScrollEvent — Add a listener for scroll events from the element using Observable.fromEvent.
  2. streamScrollEvents- Process the incoming stream of scroll events according to our requirements and condition of scroll percentage to determine when to make the api call.
  3. requestCallbackOnScroll- Once it passes our condition we call the scrollCallback which will call the API.

There is a conditional immediateCallback, if set to true we will start with DEFAULT_SCROLL_POSITION which will trigger the scrollCallback without user scrolling. So this will be our API call to get the initial data to populate the container. All the above functions are same as in my previous blog post which has detailed explanation about the RxJS Observable methods used.

Lets add infinite scroll directive to our AppComponent. Below is app.component.ts

getStories — Calls the hackerNewsService and process the return data.

Pay attention to the constructor — this.scrollCallback

this.scrollCallback = this.getStories.bind(this);

so we we are assigning the this.getStories function to scrollCallback but binding the context of this to the function. This ensures when the callback is executed within the infinite scroller directive, it will execute with the context of our AppComponent and not InfiniteScrollerDirective. You can read more about .bind here.

Our html is pretty straight forward, it has ul which has appInfiniteScroller added with parameters passed in scrollPercent, immediateCallback and scrollCallback. It renders the news title in a li.

We have basic styles for our container

Below is the infinite scroller in action using a directive in Angular2. Watch the scroller on the right.

Working Example: https://ashwin-sureshkumar.github.io/angular-infinite-scroller/

I am unable to upload gifs to this post. Here is the link to giphy http://giphy.com/gifs/xTiN0FRfyHfO538Tsc

If you liked this post, please share, comment and press the 💚 .