Make a simple Angular 2 SPA

This article shows the most basic way of making an Angular 2 SPA. The goal is to provide a hands-on demonstration and introduction to Angular 2 SPA in a simplistic way.

Things we’ll do

  1. Make a Angular 2 project.
  2. Make two pages.
  3. Make & setup the router file.
  4. Make a navigation component
  5. How to setup redirection.

Using Angular-CLI to make a project

Angular-CLI makes things easier. If you don’t have it, make sure you install it.


npm install angular-cli -g

Just like other CLI’s such as Ionic-CLI and Vue-CLI, a project will be generated for you. That project includes ready configurations, a dev server, modules to install, ready script commands, etc. You won’t have to start from scratch.

Trying to build an Angular 2 project from scratch will take a long time. The configuration is dreadful!

The project generated from Angular-CLI comes configured with Webpack and TypeScript.

Create an Angular 2 project


ng new PROJECT_NAME

Make a simple Angular 2 SPA

The above shows the Angular-CLI generating an Angular 2 project.

The project comes with a package.json which lists the dependecies and devDependencies. These modules need to be installed.


cd PROJECT_NAME 
npm install

Installation of dependencies might take a while.

Run the app

After the dependencies have been successfully installed, you can now run the app! Below is the simple command to run the app.


ng serve

Go to the browser and type localhost:4200.

Make a simple Angular 2 SPA

The image above shows what you should see on the browser.

The good thing about this project’s server configuration is that the browser automatically refreshes itself to reflect any changes you make.

Time to make a page

Angular 2.0 is a component based framework. This means that making a page is making a component.

For this example, we will mostly work in the app folder. It’s inside the src folder.

Make a simple Angular 2 SPA

Make a pages folder.

Put the pages folder inside the app folder. For structural organization, all page components should be saved in the pages folder.

The page1.component.ts

Make a page1 folder inside the pages folder.


import { Component } from '@angular/core';

@Component({
  selector: 'page-one',
  template: `<h1>Page 1</h1>`
})
export class Page1Component {

}

To make an Angular 2 component, we import Component from the Angular 2 core. Then, we use it with the @ Decorator. As you can see,@Component() is a function. It takes in an object. The selector property is like Angular 1.x’s Directive name. The template property is for the HTML tags.

It’s not sufficient to demonstrate a SPA framework by just making one page. Let’s make a second page.

The page2.component.ts

Make a page2 folder inside the pages folder.


import { Component } from '@angular/core';

@Component({
  selector: 'page-two',
  template: `<h1>Page Two!!</h1>`
})
export class Page2Component {

}

You might be wondering why we have to make a directory for each page component. This is standard for when you want to make a module, a separate HTML, CSS files, and CSS Pre-processor files for each component.

Make the Router file

The name of the file should be app.routes.ts file. This is so that we follow the file naming convention that came with this project. Save it in the src folder.


import { ModuleWithProviders } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';

/*
import Page Components
=============================================== */
import { Page1Component } from './pages/page1/page1.component';
import { Page2Component } from './pages/page2/page2.component';

export const routes: Routes = [{
  path: 'page1', component: Page1Component
}, {
  path: 'page2', component: Page2Component
}];

export const routing: ModuleWithProviders = RouterModule.forRoot(routes);

The above code shows a basic router file for an Angular 2 SPA.

The definition of the routes variable is in TypeScript; The routes variable is an instance of Routes. And, it takes in an array of objects. Each object is required to have a path and a component property. We import the page components so that we can match them to their appropriate path.

The intention is to enable access to the pages as localhost:4200/page1 or localhost:4200/page2. However if we type either one in the browser, the contents of won’t show up yet. This is because the project doesn’t know about the router file and the page components. This is why we export routing as a module at the very end of the file.

Include the page components and routing in the app.module.ts.

Importing the page components seem redundant. But we had to import the page components in the app.routes.ts file to configure the paths to these pages. And, we need to tell the app.module.ts that these pages exists. So add the page components in the declartions property of the @NgModule. Also, add routing to the imports property.


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

/* The Main Component for this SPA. */
import { AppComponent } from './app.component';
// include these somewhere above @NgModule
import { routing } from './app.routes';

/* import page components */
import { Page1Component } from './pages/page1/page1.component';
import { Page2Component } from './pages/page2/page2.component';

@NgModule({
  declarations: [
    AppComponent,
    // The page components
    Page1Component,
    Page2Component
  ], 
  imports: [
    BrowserModule,
    routing
  ]
})

Before we test and see the pages appear in the browser, we have to add the <router-outlet> in the root component’s html template. This component is responsible for showing the page components that we setup in the router and included in the root module. Open the app.component.html. It should be in the app folder.


<h1> {{title}}</h1>
<div>
 <router-outlet></router-outlet>
</div>

Now type in localhost:4200/page1 in the browser. You’ll see the contents of page 1. If you type localhost:4200/page2, you’ll see the contents of page 2.

Make an simple Angular 2 SPA

Make a simple Angular 2 SPA

If you only typed localhost:4200, the page 1 content didn’t show up. This is because we didn’t setup a default redirection in router file.

Redirection

Let’s make page 1 show up by default. Go to the app.routes.ts.

Add another object in the routes instance:


export const routes: Routes = [{ 
  path: 'page1', component: Page1Component 
}, { 
  path: 'page2', component: Page2Component 
}, /* This new object is the redirection*/ 
{ path: '**', redirectTo: '/page1' }
];

The ** is a wildcard. So if you type localhost:4200, page 1 will show up. If you type localhost:4200/abcd, page 1 will show up because path abcd doesn’t exist. Everything redirects to page 1 except page 2 since it is defined.

Bonus: Navigation Component

Constantly typing in the browser’s address bar is not ideal. Especially, if the end users don’t know all of the paths. That’s why navigation menus exist. Let’s make a navigation component.

You can skip this part. But the real bonus part is learning how to make a component that’s not a page. This type of component should be inside the components folder in app folder. This way, we can differentiate page components and other non-page components.

Make a nav-menu folder. This folder will contain the implementations of a navigation component. Then, make a nav-menu.component.ts file.


import { Component } from '@angular/core';

@Component({
  selector: 'nav-menu',
  template: `
    <nav>
      <a [routerLink]="['/page1']">
        Page1
      </a>
      <a [routerLink]="['/page2']">
        Page2
      </a>
    </nav>
  `
})
export class NavMenuComponent { }

The template has the HTML <nav> element. And in it, there are two anchor tags <a>. Without Angular 2, we’d be using the href attribute for the anchor tags. But Angular 2’s Router provides the RouterLink directive. As you can see, we use it as property binding that takes in an array. In the end, it translates to <a href="/page1"> in the browser. So things still work. We do this so that we avoid hard coding routes. We also do this so that we can easily pass parameters:


['routePath', param1, { prop1: val1, prop2: val2 } ....] 

Include the navigation in the app.module.ts.


. . .
import { NavMenuComponent } from './components/nav-menu/nav-menu.component';
. . .

@NgModule({
   declarations: [
      AppComponent,
      Page1Component,
      Page2Component,
      //Add the navigation component
      NavMenuComponent
   ]
   . . .
})

Now that the root app module knows about the NavMenuComponent, we need to add it in the html template. Open the app.component.html file and add the <nav-menu> above the <router-outlet>.


<h1>{{title}}</h1>
<div>
  <nav-menu></nav-menu>
  <router-outlet></router-outlet>
</div>

Make a simple Angular 2 SPA.

This project has been uploaded to GitHub!

Ending

Although Angular projects can get very large, this article only show the basics. Hopefully, Angular 2 won’t be intimidating anymore, and all this information clarifies how to make a SPA.

If you read this article all the way to get your feet wet with Angular 2, then I hope you’ll immerse yourself in Angular 2 even more.