This is the first part of building an Earnings Tracker using Angular and TypeScript Series.
The source code for this tutorial series is published on GitHub. Demo application is hosted in Microsoft Azure.
Part 1: Create an Angular SPA in TypeScript
In the previous tutorial series, we created the Earnings Tracker Web API in ASP.NET Core. In this tutorial, we will use Visual Studio Code to build the initial structure of the Angular Single-Page Application (SPA) in TypeScript.
Client-Side Technologies
The application structure, styles, and patterns follow the recommendations outlined in the official Angular Style Guide.
I use the official Angular Developer Guide as a reference to write this tutorial series.
Prerequisites
The following are required to complete this tutorial:
- Build the QuickStart app if you are new to Angular
- Install Node.js and npm (Nods.js > 6.3.x and npm > 3.10.x) on your machine if you haven’t done so already
Task 1. Set up the Project Structure
I prefer to organize my project based on components/modules. Building a maintainable, scalable, and well-organized application should start from the beginning. Using DRY and SRP patterns, we will create smaller code files that each handle one specific job. This approach has helped me personally to locate, enhance, and debug requested features from clients quickly.
-
Let’s creating folders and copying files to C:\_tutorials\angular-earnings-tracker from GitHub as listed below:
angular-earnings-tracker
|--api
|--dashboard.json
|--settings.json
|--app
|--dashboard
|--navbar
|--settings
|--content
|--css
|--animate.css
|--keen-dashboards.css
|--loading-bars.css
|--styles.css
|--images
|--favicon.ico
|--loading-bars.svg
|--js
|--loading-bars.js
|--package.json
|--systemjs.config.js
|--tsconfig.json
-
Lines 20-22 list the package definition and configuration files:
- package.json: defines scripts and serves as documentation for what packages the Earnings Tracker depends on.
- systemjs.config.js: loads application and library modules.
- tsconfig.json: is a configuration file to guide the TypeScript compiler as it generates JavaScript files.
Task 2. Install the Packages
Open the terminal window, enter the npm install
command to install all listed packages and libraries in package.json using npm
.
Task 3. Create startup page
-
Add the index.html file to the angular-earnings-tracker folder.
-
Replace the code in this file with the following:
<html>
<head>
<base href="/">
<title>Angular Earnings Tracker by Cathy Wun</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- 1. Load css -->
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" >
<link rel="stylesheet" href="content/css/animate.css" >
<link rel="stylesheet" href="content/css/loading-bars.css" >
<link rel="stylesheet" href="content/css/keen-dashboards.css">
<link rel="stylesheet" href="content/css/style.css">
<!-- 2. Load libraries -->
<!-- 2.1 Polyfill(s) for older browsers -->
<script src="node_modules/core-js/client/shim.min.js"></script>
<script src="node_modules/zone.js/dist/zone.js"></script>
<script src="node_modules/reflect-metadata/Reflect.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<!-- 2.2 Vendor js libraries -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- 3. Configure SystemJS -->
<script src="systemjs.config.js"></script>
<script>
System.import('app').catch(function(err){ console.error(err); });
</script>
</head>
<body class="application">
<!-- 4. Display the application -->
<earnings-tracker-app>
<!-- Show simple splash screen-->
<div class="splash">
<div class="color-line"></div>
<div class="splash-title">
<h1>Angular Earnings Tracker</h1>
<img src="content/images/loading-bars.svg" width="64" height="64" title="" alt="" />
</div>
</div>
</earnings-tracker-app>
</body>
</html>
The index.html file serve as our startup page. It performs the following functions:
- loads our resources (.css and .js)
- configures
SystemJS
to load library modules and launch our application by running the AppModule
in the main.ts file - renders our application’s component between the
earnings-tracker-app
tags - shows our splash screen
Task 4. Bootstrap our application
-
Add the main.ts file to the app folder.
-
Replace the code in this file with the following:
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule);
Line 9 bootstraps the imported AppModule
from app.module.ts file using the Just in Time
(JIT) complier to launch the application.
Task 5. Create the root module
By convention, every Angular app has a root module class called AppModule
in app.module.ts file. The @NgModule decorator allows us to bundle components, services, pipes, and directives at the module level. If you want to learn more about the benefits of using @NgModule
, please check out Rob Wormald's blog post.
-
Let’s add app.module.ts file to the app folder.
-
Replace the code in this file with the following:
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { NavbarComponent } from './navbar/navbar.component';
import { DashboardModule } from './dashboard/dashboard.module';
import { SettingsModule } from './settings/settings.module';
import { AppRoutingModule } from './app-routing.module';
@NgModule({
imports: [ BrowserModule,
HttpModule,
DashboardModule,
SettingsModule,
AppRoutingModule
],
declarations: [ AppComponent, NavbarComponent ],
bootstrap: [ AppComponent]
})
export class AppModule { }
-
Lines 17 – 22 import the following supporting modules whose exported components, directives, or pipes are referenced by the component declared in the AppModule
.
BrowserModule
: provides critical services that are essential to launch and run our app in the browser HttpModule
: provides http
services DashboardModule
: provides collections of Dashboard
functionality SettingsModule
: provides collections of Settings
functionality AppRoutingModule
: is a routing module
which provides the top level application-wide configured services with routes in the root module
-
Line 23 declares a list of components (AppComponent
, NavbarComponent
) that belong to the AppModule
.
-
Line 24 bootstraps the root component named AppComponent
when Angular starts the application.
-
Line 27 exports the AppModule
so that the main.ts file can import it.
Task 6. Configure routes for the Router
The application will have a routing module
named AppRoutingModule
. It serves as a central place to maintain top level application routing configuration.
Most developers should always implement a Routing Module for the sake of consistency. It keeps the code clean when configuration becomes complex. It makes testing the feature module easier. Its existence calls attention to the fact that a module is routed. It is where developers expect to find and expand routing configuration.
Angular
To learn more about Routing & Navigation
, please see the official documentation here.
-
Add the app-routing.module.ts file to the app folder.
-
Replace the code in this file with the following:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
export const appRoutes: Routes = [
{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },
{ path: '**', redirectTo: '/dashboard' }
];
@NgModule({
imports: [RouterModule.forRoot(appRoutes, { useHash: true} )],
exports: [RouterModule]
})
export class AppRoutingModule {}
-
Lines 4 – 9 configure our Router with two routes:
- 1st Route: when initial relative URL is empty (for example: http://localhost:3000) , redirect to another route whose path segment is
/dashboard
- 2nd Route: when URL doesn’t match any routes defined in our configuration, redirect to another route whose path segment is
/dashboard
-
Line 12 uses RouterModule.forRoot
method to register two routes with the Router.
-
Line 13 re-exports the RouterModule
by adding it to the module exports
array. Since we imported AppRoutingModule
with the root module named AppModule
, the components declared in AppModule
will have access to router directives.
- Line 16 exports the
AppRoutingModule
so that the AppModule
in app.module.ts file can import it.
Task 7. Create our root component and its view
-
Add the root component named app.component.ts file to the app folder.
-
Replace the code in this file with the following:
import { Component } from '@angular/core';
@Component ({
selector: 'earnings-tracker-app',
templateUrl: 'app/app.component.html',
})
export class AppComponent {}
The AppComponent
is our application shell.
-
Add the view named app.component.html file to the app folder.
-
Replace the code in this file with the following:
<!-- Navigation Area -->
<et-navbar></et-navbar>
<!-- End Navigation Area -->
<!-- Content Area -->
<div class="container-fluid">
<!-- Routed View -->
<router-outlet></router-outlet>
</div>
<!-- End Content Area -->
The app.component.html file contains the master layout for our HTML. It provides a shell
with two regions: a navigation area and a content area. The navigation area renders the navbar
view between the et-navbar
tags. The content area uses router-outlet
directive to display the views produced by the Router. In other words, when you click a navigation link, it’s corresponding view is loaded in the content area.
Task 8. Create the Navbar component and its view
-
Add the navbar.component.ts file to the navbar folder.
-
Replace the code in this file with the following:
import { Component } from '@angular/core';
@Component ({
selector: 'et-navbar'
,templateUrl: 'app/navbar/navbar.component.html'
})
export class NavbarComponent {
heading = 'Angular Earnings Tracker';
}
The navigation area of the AppComponent
uses et-navbar
to display the navbar
view.
-
Add the view named navbar.component.html file to the navbar folder.
-
Replace the code in this file with the following:
<div class="navbar-nav navbar-inverse navbar-fixed-top" role="navigation">
<div class="container-fluid">
<div class="navbar-header">
<a class="navbar-brand" routerLink="/dashboard" routerLinkActive="active">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
<a class="navbar-brand" routerLink="/dashboard" routerLinkActive="active">{{heading}}</a>
</div>
</div>
</div>
The navbar.component.html uses Bootstrap for quick styling and building responsive layouts. It uses routerLink
directive to represent navigation menu items.
-
We have the following links in navigation menu:
<
Angular Earnings Tracker
When you click either the < or the Angular Earnings Tracker link in the navigation menu, the Dasboard
view will be placed in the content area of the AppComponent
view:
In the next tutorial, we will build the Angular Dashboard Feature Module using TypeScript.
The source code for this tutorial series is published on GitHub. Demo application is hosted in Microsoft Azure.
References