DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
The Latest "Software Integration: The Intersection of APIs, Microservices, and Cloud-Based Systems" Trend Report
Get the report
  1. DZone
  2. Coding
  3. Frameworks
  4. Angular 2: Attribute @Directive() and Creating An Infinite Scroll Directive

Angular 2: Attribute @Directive() and Creating An Infinite Scroll Directive

How to make Angular apps more dynamic by adding an infinite scroll directive.

Oren Farhi user avatar by
Oren Farhi
·
Feb. 08, 16 · Opinion
Like (4)
Save
Tweet
Share
21.99K Views

Join the DZone community and get the full member experience.

Join For Free

In the recent article, I used the new "ng-repeat" in angular 2, "NgFor", and created component that consumes other custom component. In this article, I continue to show further development for Echoes Player with Angular 2, this time - making it more dynamic by adding an infinite scroll directive, what is known in Angular 2 as an attribute directive.

Angular 1.x Infinite Scroll

In the current production of Echoes Player, in order to add more videos to the result while scrolling, I used "ng-infinite-scroll". It has a nice minimal directive api for triggering an infinite scroll — and the usage for Echoes Player is quite simple:

<div class="view-content youtube-results youtube-videos" 
infinite-scroll="youtubeVideos.searchMore()" 
infinite-scroll-distance="2"
>
....
</div>

There are more attributes as an api for this directive, however, in this case — I didn't use it.

As of this time of writing this post, I didn't found any angular 2 infinite scroll directive / component, so, I figured it is a great opportunity to migrate "ng-infinite-scroll" directive from angular 1.x to angular 2 while learning how to create one.

Please note that the source code for this angular 1.x infinite scroll directive is written with "coffeescript". However, the production ready code is compiled eventually to ES5.

Migration Process to Angular 2 Infinite Scroll

After converting the source code back to JavaScript (using http://js2.coffee/), I started isolating the code to understand what it does and being able to migrate it to ES2015 class.

Most of the important logics is written as an angular 1.x controller. I figured this code should be an ES2015 class. Actually, I wanted the migrate the logics of this controller to an ES2015, So it will be agnostic to any framework/library, being able to use it anywhere — the same principal applied to ponyfoo's dragula and his other awesome components.

But first, I had to understand angular 2 directive concepts.

Angular 2 Directive In a Nutshell

In Angular 2, aside from components, there are still directives. There are built-in directive to the framework, such as: NgFor, NgIf, NgModel, NgClass and there's an api for creating custom directives.

Essentially, a directive is something like a component.

There are 3 kinds of directives:

  1. A Component — Using @Component()
  2. A Structural Directive — Using @Directive() - usually changes the DOM of an element - NgIf
  3. An Attribute Directive — Using @Directive() - doesn't change the DOM, but adding behaviour

Infinite Scroll fits well to an Attribute Directive (More on that on the official documentation) — It adds a scroll event (behavior) to an element and acts upon it.

Lets create the Angular 2 wrapping code for this directive.

First, lets import the relevant dependencies:

import { Directive, ElementRef, Input, Output, EventEmitter } from 'angular2/core';
import { Scroller } from './scroller';

The logics and migrated code of angular 1.x is imported from the "scroller.ts" class file.

We're going to use some of Angular's 2 core objects to define the relevant properties.

Directive Definition

To declare an attribute as a directive, similar to Component, we use the "@Directive()" decorator, while specifying an attribute class selector (css selector):

@Directive({
  selector: '[infinite-scroll]'
})

Directive Bindings and Events

Next, we'll define the class which will used as a controller for this directive, an input data that we'll expect to get from the element and an event that this directive will expose.

export class InfiniteScroll {
  @Input() set infiniteScrollDistance(distance: Number) {
    this._distance = distance;
  }

  @Output() scroll = new EventEmitter();

//...
}

The "infiniteScrollDistance" property is expected to be set from outside the directive, as an attribute API. The same goes for the "scroll" event, which will trigger a function that is bind from outside. This means, that we'll use this directive like so:

<div class="search-results"
    infinite-scroll
    [infiniteScrollDistance]="2"
    (scroll)="onScroll()">
</div>

Notice how each attribute in the above "div" element is matching a different declaration in this directive code.

Referencing Directive's Element in Angular 2

With angular 1.x, the DI system allowed us to require "$element" and expect to get a reference to the directive's DOM element:

controller: function ($element) {
$element.on('scroll', onScroll);
}

With angular 2, we use the "ElementRef" type definition. Also with the use of Typescript, we'll attach its property reference to "this" directive context:

constructor(private element: ElementRef) {
   // now, we can reference to: this.element
}

Hook the Scroll Event With ngOnInit to Directive's Element

Now, we'll us angular 2 hook — "ngOnInit" — which will run when the directive is ready and will instantiate a new scroller, only once. Notice that I bind "this" context to the onScroll function reference to keep the context of this directive when the scroll event will trigger the event emitter's property, scroll:

ngOnInit() {
    this.scroller = new Scroller(window, setInterval, this.element, this.onScroll.bind(this), this._distance, {});
  }

  private scroller: Scroller;

  private _distance: Number;

  onScroll() {
    this.scroll.next({});
  }

Migration of Scroller Logic

The "scroller.ts" is an ES2015 class (full source code). Much of this code has been copied from the source implementation of "ng-infinite-scroll" of angular 1.x and has been adapted to follow ES2015 syntax and relevant updates to the code as much as possible.

Final Thoughts

Still, the infinite-scroll directive is not complete and there are more features to port from the original angular 1.x version. There are also some points in the code where it is points to angular 2 specific "this.$elementRef.nativeElement" in order to get the actual DOM element.

Echoes Player implementation with ng2 is open source. You can also fork Echoes ES2015 with Angular 1.x version and follow the complete conversion from ES5 to ES2015 of this project.

The Goal of echoes-ng2 is migrating the whole application code to use angular2 various features.

Directive (programming) AngularJS Attribute (computing)

Published at DZone with permission of Oren Farhi. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • OpenVPN With Radius and Multi-Factor Authentication
  • gRPC on the Client Side
  • Building a REST API With AWS Gateway and Python
  • Java Concurrency: LockSupport

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: