A Stock Portfolio using Angular 6 : Routing

Hashtags

Routing is a cornerstone of single page applications (SPA’s). In SPA’s, a single page is loaded and the application resides within it. Re-loading the page or navigating to a new page or url is a no-no.Keeping the url static for the lifetime of the SPA is equally bad. Static urls don’t allow the web browser to collect history. Without history the web browser’s back button will just go to whatever site you visited previously – even if you spent 10 minutes judiciously navigating around the SPA. Bookmarks will become meaningless as well.

The Hash

So changing the url is mostly bad. A way around this is using hashes (#) in the URL Path. Hashes were initially used to navigate within a page to different anchor tags ( <a/> ) on the same page. They don’t cause a page refresh and are collected in the web browser’s history. A good example is a page that has a table of contents in the header. Clicking the hyperlinks in the table of contents scrolls down to that particular section on the page which is tagged with anchor. Adding ( or removing ) hashes to the URL does not cause the page to refresh.

This doesn’t cause a page refresh :

http://www.myapplication.com/quote#addnews

…this does :

http://www.myapplication.com/quote/addnews

In general, routing in a SPA leverages URL hashes. Navigating to different parts of the application changes the page’s URL by manipulating hashes.

Routing in Angular

In Angular, Routing loads a Component given a URL Path. This was my first stab at a Routing Table for the Stock Portfolio Application.

const appRoutes: Routes = [

  { path: 'quote', component: TickerComponent },
  { path: 'quote/:id', component: TickerComponent,
    children:[
      { path: 'details', component: TickerContainerComponent},       
      { path: 'addNews', component: TickerNewsAddComponent}, 
      { path: 'addSymbol', component: TickerAddComponent},       
    ] },
  { path: '', redirectTo: '/quote', pathMatch: 'full'}
];

So, ../quote/msft will load the TickerComponent with ticker info for Microsoft.

And the “Child Route” ../quote/msft/details will load the TickerContainerComponent as a child element of the TickerComponent.

Child Routes

Child routes allow you to display a child component within a parent component based upon the URL. Typically, the Application component template contains a <router-outlet> directive that displays the initial Component. Parent Components follow a similar pattern. They will likewise have a <router-outlet> directive in which their child component gets loaded.

To clarify I should point out that the ultimate routing table that I ended up using for the Stock Portfolio does not use child routes. I just wanted to give a quick overview of them here as well, I almost used them.

The Routing Module

This is what the Routing Module ( minus the Routing Table ) looks like :

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { APP_BASE_HREF} from '@angular/common';

import { TickerComponent } from './components/ticker/ticker.component';
import { TickerAddComponent } from './components/ticker-add/ticker-add.component';
import { TickerNewsAddComponent } from './components/ticker-news-add/ticker-news-add.component';
import { TickerContainerComponent } from './components/ticker-container/ticker-container.component';

const appRoutes: Routes = [
	/* Routing Table */
];

@NgModule({
 providers: [
    {provide: APP_BASE_HREF, useValue: '/stockapp'}
  ],

  imports: [
    RouterModule.forRoot(
      appRoutes,
      { enableTracing: true } // <-- debugging purposes only
    )
  ],
  exports: [
    RouterModule
  ]
})
export class AppRoutingModule {}


Make sure that you import all of the Components that are loaded by the URL Paths into the Module. The router needs to know about the Components it should load.

What is APP_BASE_HREF?

After migrating routing to a Module I kept getting an error when running my unit tests for the “root” AppComponent:

“Please provide a value for the APP_BASE_HREF token or add a base element to the document.”

Strangely, the error was NOT occuring at runtime. To fix the error I followed these instructions on the Angular website. The router needs to know which “base url” to use when navigating to your routes.

Why a Separate Module?

Best practices dictate that routing should be kept in a separate module from the rest of the application. Another best practices should also be to explain why doing something as such is a best practice. Unfortunately, the official Angular documentation dictates it as such and glosses over the “why”. I’ll take a stab at it :

  1. Seperation of Concerns. Components shouldn’t care what URL invoked them. They should be stand-alone and isolated from such things.
  2. Strategy Pattern. Keeping routing in a seperate module makes it easier to change which URLs launch which Components.

In a hurry?

The finished source code is available on my GitHub repository.

The finished application is up-and-running on Heroku here. Be aware that it is running on a “free” development server so give it a minute or so to spool up.

That’s it for now

Please let me know if you have any questions or comments. If you want to start from the beginning please go here.

A Stock Portfolio using Angular 6 : Finding a Financial Web Service

I want live data form my stock portfolio application. Alpha Vantage provides a “free” REST service that supports a plethora of calls for retreiving stock information. If you go here you can make calls against their services. To make calls from your own application however you are going to need to generate your own unique API Key.

CORS

The cool thing about Alpha Advantage is that their REST services are CORS-enabled. CORS-enabled services can be called directly from a web browser without being blocked by cross-domain policies. Typically, a web browser will not allow you to GET data from a domain other then the one your application is running on. So, http://www.mysite.com/myapp can not make calls to http://www.yoursite/yourservice. CORS includes a special headers in the REST HTTP Request, “Access-Control-Allow-Origin” that circumvents this restriction. Prior to CORS and it’s predecessor ( JSONP) I would of had to expose a proxy service on the web application running the stock portfolio application. The proxy service wouldn’t be restricted by cross-domain policies as it would be running on the server. The web-browser would call the proxy service which would in turn call the service residing on another domain.

To get a quote for a stock we’re going to make this REST call against Alpha Vantage. This is what the result looks like :

{
    "Global Quote": {
        "01. symbol": "MSFT",
        "02. open": "99.3000",
        "03. high": "99.7500",
        "04. low": "96.4000",
        "05. price": "99.2400",
        "06. volume": "33233175",
        "07. latest trading day": "2018-12-27",
        "08. previous close": "100.5600",
        "09. change": "-1.3200",
        "10. change percent": "-1.3126%"
    }
}

A Strongly-Typed Quote Model

Although we could store the quote as-is it would be a better idea to create a Strongly-Typed Model for it using Typescript. By using a Strongly-Typed Model :

  • The signature of the result will be known to downstream consumers – eliminating guesswork and confusion.
  • Typescript provides validation support. The compiler will notify you if you’re trying to access field on the Model that does not exist.

This is what my Quote Model looks like :

export class Quote {

    constructor ( symbol: string, open: number, high: number, low: number, price: number, volume: number, latestTradingDay: string, previousClose: number, change: number, changePercent: number ) {
        this.symbol = symbol;
        this.open = open;
        this.high = high;
        this.low = low;
        this.price = price;
        this.volume = volume;
        this.latestTradingDay = latestTradingDay;
        this.previousClose = previousClose;
        this.change = change;
        this.changePercent = changePercent;
    }

    symbol: string;
    open: number;
    high: number;
    low: number;
    price: number;
    volume: number;
    latestTradingDay: string;
    previousClose: number;
    change: number;
    changePercent: number;
} 

An Angular Service

I created a Ticker Service to fetch the quote from Alpha Vantage’s REST service, wrap it up as a Quote object, and then return it. As REST service calls are asynchoronous the Quote is returned as an Observable. The Ticker Service returns the Observable immediately – even if the REST call hasn’t completed :

...
export class TickerService {

  ...

  getQuote(ticker: string) : Observable {

    let url = ...

    return this.http.get(url).pipe(map( res => new Quote(
		res["Global Quote"]["01. symbol"],
		res["Global Quote"]["02. open"],
		res["Global Quote"]["03. high"],
		res["Global Quote"]["04. low"],
		res["Global Quote"]["05. price"],
		res["Global Quote"]["06. volume"],
		res["Global Quote"]["07. latest trading day"],
		res["Global Quote"]["08. previous close"],
		res["Global Quote"]["09. change"],
		res["Global Quote"]["08. change percent"]
    )));

  }
}

The consumer/client subscribes to the Observable – and waits. When the REST service data is finally fetched, “subscribe” is invoked along with a “data” object (the desired Quote). This code snippet is from the Ticker Service’s Unit Test

...
describe('TickerserviceService', () => {
	...

	it('should return a quote (MSFT)', () => {
		const service: TickerService = TestBed.get(TickerService);
		service.getQuote("MSFT").subscribe( data => {        
			expect(data.symbol == "MSFT");
		});

	});
});

In a hurry?

The finished source code is available on my GitHub repository.

The finished application is up-and-running on Heroku here. Be aware that it is running on a “free” development server so give it a minute or so to spool up.

Next up?

Hooking up Basic Routing

Or, start from the beginning.

A Stock Portfolio using Angular 6 : Requirements, Components, and Mock-ups

The requirements presented to me for the coding challenge were pretty sparse :

  1. Create an application for managing “news” articles for a user’s stock portfolio.
  2. It needs to be responsive so it displays nicely on a variety of devices.

Naturally, I had to add my own requirements :

  1. The users’ stock portfolio and news needs to be persistent; a user should not have to re-create their portfolio every time they use the application.
  2. Stock data for the users’ portfolio needs to be refreshed in real-time.
  3. The user should be able to view historical data for a stock in a chart.

Why Components are Awesome

The cool thing about modern web frameworks is that they force you to compartmentalize your stuff into reusable widgets. So, instead of a huge monolithic Javascript file you have a bunch of self-enclosed “widgets”. Each “widget” performs a specific task and has it’s own javascript, html, css, and tests. A “widget” can be used for fetching data or displaying a particular section of markup. This a huge boon when working on large projects on a large team as it allows you to break up the work more easily.

Stock Portfolio Components

I broke up the application into 8 Components: The NavigationComponent will always be displayed in the header. Clicking on “Add Symbols” will bring up the TickerAddComponent which will allow the user to add stock symbols. Clicking on “Add News” will bring up the TickerNewsAddComponent which will allow the user to add news for a stock symbol. The TickerComponent will be displayed on the “home” page. Clicking on a stock symbol will bring up the TickerContainerComponent which hosts the TickerChartComponent, TickerDetailsComponent, and TickerNewsComponent.

Mock-up

This is a mock-up of what the Components looks like as well as their interaction.

In a hurry?

The finished source code is available on my GitHub repository.

The finished application is up-and-running on Heroku here. Be aware that it is running on a “free” development server so give it a minute or so to spool up.

Next up?

Finding a financial web service.

Or, start from the beginning

A Stock Portfolio using Angular 6 : Challenge Accepted

The Interview Coding Challenge

I’m interviewing right now. One thing that has changed dramatically since I last interviewed is …. the dreaded “Coding Challenge”. What used to consist of a quick whiteboarding excercise has now progressed into the design and development of an entire application. The good news is that employers typically allow you to do it from the comfort of your own home and at your own pace. The bad news is that the challenges can be quite elaborate.

A Stock Portfolio using Angular 6

One of the coding challenges that I was presented with by an employer was to develop a “stock portfolio” application that would allow you to enter stock tickers and news articles. The rules were vague: I just needed to use a newer Javascript Framework ( React, Angular, Vue, etc … ) as well as a Presentation Framework ( Angular Material, Bootstrap, etc… ).

I accepted the challenge, started working on it, and then quickly realized how much cooler the stock portfolio application could be with some additional features. I coul pull in Local Storage, a Live Stock Feed, Charting! Professionally this would be taboo – a bad case of what is know as scope creep. However, being unemployed with some extra time on my hands I felt it was an opportunity to showcase something pretty cool.

In a hurry?

The finished source code is available on my GitHub repository.

The finished application is up-and-running on Heroku here. Be aware that it is running on a “free” development server so give it a minute or so to spool up.

Next Up?

Requirements, Components, and Mock-ups.