Angular2 -HackerNews clone Firebase setup with observables — Realtime

Written by Sureshkumar_Ash | Published 2017/01/27
Tech Story Tags: angular2 | javascript | angular-material | firebase | hacker-news

TLDRvia the TL;DR App

This is the third post in the series of building a HackerNews clone with Angular 2, Angular Material and Firebase. This post we will setup firebase and we will pull in and display the top stories, new stories from hackernews.

Previous posts :

  1. Setting up Angular2 and Angular Material with Angular CLI.
  2. Components and Routers — Initial Setup

Next post:

Dynamic Components, Routing Params and Refactor

Create an account with Firebase here and create a new project, we need only the API key for this project for now. After creating the project grab the API key from the project by clicking on Add firebase to web app.

We will be using AngularFire2 — official library for Firebase and Angular2. We will use moment and angular2-moment for date time manipulations.

Below are the setups that we will be doing in this post,

  1. Configure AngularFire, Firebase, Moment and Angular 2 Moment to our application
  2. Create a service to interact with HackerNews Firebase API
  3. Register our service to app module
  4. Create a new module for shared components under shared (Story Component to be shared across modules like top stories, newest stories)
  5. Create a new module for Top Stories and pull in top 100 from the service
  6. Update newest module to pull in the newest stories with shared component and service.
  7. Update the app.routing.ts to load top stories as default.

#STEP 1

npm install angularfire2 firebase moment angular2-moment --save

Open up app.module.ts import dependencies and configure AngularFire. For databaseURL will be using the HackerNews Firebase Database Url provided in the documentation. Take sometime to go through the API documentation, understanding the API is important.

import { AngularFireModule } from 'angularfire2';import * as firebase from 'firebase';import * as moment from 'moment';

@NgModule({declarations: [AppComponent,HeaderComponent],imports: [BrowserModule,MaterialModule.forRoot(),RouterModule.forRoot(routes),AngularFireModule.initializeApp({apiKey: '<API_KEY>',databaseURL: 'https://hacker-news.firebaseio.com',authDomain: '<AUTH_DOMAIN>'}),NewestModule],providers: [],bootstrap: [AppComponent]})

#STEP2

Under /src/app — we are going to create shared folder which will host our shared code for our application like utils, services, etc., Right now we are creating our hackernews service.

As we registered AngualrFire in our app module — the configuration will be accessible across the application. Open up hacker-news.service.ts

import { Injectable } from '@angular/core';import { AngularFire, FirebaseListObservable } from 'angularfire2';

@Injectable()export class HackerNewsService {

constructor(private af: AngularFire) { }

getNewestStories(limit: number) {return this.af.database.list('/v0/newstories', {query: {limitToFirst: limit,orderByKey : true}});}

getItem(id: number) {return this.af.database.object('/v0/item/' + id);}

}

Here we are creating an injectable class with three methods.

getTopStories — Returns ids of newest stories with a limit passed

getNewestStories — Returns ids of newest stories with a limit passed.

getItem — Returns the single item object.

this.af.database.list('v0/newstories') — _What database is this accessing ?_As the configuration is across the application. We configured AngularFire in our app.module.ts to access HackerNewsAPI on Firebase (docs) .

The cool thing in AngularFire2 is you can pass an Observable to query properties like limit, etc., instead of a number —docs

#STEP3

Register our hacknews service to our services module.

import { NgModule } from '@angular/core';import { HackerNewsService } from './hacker-news.service';

@NgModule({imports: [],exports : [],declarations: [],providers: []})export class ServicesModule{static forRoot() {return {ngModule: ServicesModule,providers: [HackerNewsService]}}}

export {HackerNewsService}

The last three lines is a helper I write always so I can access all the services from within application from this single module instead of going to individual folder in the import statement. You can see the import statement for HackerNewsService in Step4.

#STEP4

Generate a module Components under shared folder and generate a component ng g component story

We are going to create a component which takes id as an input — retrieves the item from HackerNewsService and renders it.

We have a setter method for the property id, when the id changes we call the HackerNewsService to retrieve the new story.

Import MomentModule from angular2-moment and MdCardModule from angular-material. We will use md-card component from angular-material to display our story. Below is our template file, I am using pipes from angular2-moment to display the time.

Styles for the story component

#STEP5

Create a new module and component for top stories — refer to the previous blog post

I will show the component and the markup first, then we will go one by one to see what it does. I am pasting a screenshot of the code so it is well formatted.

We are importing MdCardModule in _topstories.module.ts_ as we will using in our template to display each story

So we are importing HackerNewsService, FirebaseListObservable from respective modules.

I am getting the top 100 stories from the top stories in hackernews which is currently configured at limit property within our component.

On ngOnInit — We are calling the HackerNewsService to get the top 100 stories.

trackByForStory method — is used in the [trackBy](https://angular.io/docs/ts/latest/api/common/index/NgFor-directive.html) section of ngFor in our template.

#STEP6

Perform similar steps on top stories to update the newest component.

#STEP7

Open the app.routing.ts and update the path to redirect to topstories and add a new route.

Thats the top stories page.

The app is deployed in firebase hosting (another post). The url is https://hackernews-clone.firebaseapp.com/. and the repo is actively worked around.


Published by HackerNoon on 2017/01/27