Pt.1: Setup — Splash Page Code Along — Angular, Angular Material, and Firebase

Aaron Phillips
6 min readMar 6, 2019

--

The splash page at the end of pt.1 and pt.2

This is the first post in a series where we’ll be building out a beautiful Angular (V7), Angular Material, and Firebase web app together.

In this post we’ll cover:

  1. Setting up
  2. Routing

In this post we’ll focus on setting up the project and creating the routing. At the end of the second post we’ll have created a beautiful splash page with register and login functionality using firebase, a route guard for blocking users who do not have an account yet, custom password confirmation validation, and a sexy video of clouds playing in the background.

I’m assuming basic understanding of the Angular framework (i.e. you know what components and services are), how to navigate around the terminal, and also familiarity with TypeScript.

I’m working on creating video code-alongs with each part of this project to accompany this format.

Side-note: Got ideas of what you want to see in this project? Have a read of the closing paragraph at the end of this post :)

Diving right in!

1. Setting Up The Project

If you don’t already have @angular/cli installed globally

You can check if you have @angular/cli installed globally by heading to your terminal and running

> ng v

Note: All code snippets prepended with “>” will be terminal commands.

If you don’t get a version printed and instead get an error message of some sort, then you can install it in the terminal using:

> npm install -g @angular/cli

You may need “sudo” at the beginning if on mac or linux.

Creating The Project

Over in the terminal navigate to the folder you wish to contain the project and run:

> ng new landing-page

This will tell Angular cli to create us a new Angular project called “landing-page”.

We’re going to say no to routing (we will create our routes from scratch) and select SCSS stylesheets.

Creating The Components, Service and Guard

Now we’re going to create all the files that we’re going to require. But first, a quick tutorial on Angular cli shortcuts: g=generate, c=component, s=service, g=guard.

Okay, so we’ll need components for user registration, login, and home. But we’re also going to create a component which renders the registration and login components — using a router-outlet — let’s call this “Auth”. Don’t worry if this sounds daunting, I’ll explain this later.

The auth guard is what will stop the user entering home when they’re not authenticated, and the service is where we’ll keep the code which talks to Firebase.

> ng g c auth
> ng g c home
> cd landing-page/src/app/auth
> ng g c register
> ng g c login
> ng g s auth
> ng g g auth

Setup Firebase

Firebase is amazing for really quickly getting up and running with authentication. It does everything behind the scenes for us, and we just need to provide the UI.

The team at Google have made our lives even easier when developing Angular applications with Firebase by creating a project called AngularFire. To install it run:

> npm install --save firebase @angular/fire

In your firebase console create a new project and click add to web app. A popup should appear, giving you your apiKey, authDomain, etc. We’re going to copy this into “/src/environments/environment.ts”. After, the code should look something like this:

// environment.tsexport const environment = {
production: false,
firebase: {
apiKey: '<your-key>',
authDomain: '<your-project-authdomain>',
databaseURL: '<your-database-URL>',
projectId: '<your-project-id>',
storageBucket: '<your-storage-bucket>',
messagingSenderId: '<your-messaging-sender-id>'
}

};

We need to let Firebase know to expect users registering and signing in using their email and password. So head back over to your firebase console and use the side menu to navigate to the Authentication page, then enable email and password login method using the toggle.

Now we just need to initialise firebase in our app and add the AngularFire modules we’re going to use. Our “app.module.ts” will look something like this:

// app.module.tsimport { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AngularFireModule } from '@angular/fire';
import { AngularFirestoreModule } from '@angular/fire/firestore';
import { AngularFireAuthModule } from '@angular/fire/auth';
import { environment } from '../environments/environment';
@NgModule({
imports: [
BrowserModule,
AngularFireModule.initializeApp(environment.firebase),
AngularFirestoreModule,
AngularFireAuthModule,
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule {}

Setup Angular Material

I’ll simply be following angular material’s setup docs here, so if you’d like more information or alternative set up methods just visit https://material.angular.io/guide/getting-started.

Back in the trusty terminal:

> npm install --save @angular/material @angular/cdk @angular/animations

Import animations in “app.module.ts”, along with all the material modules we’re going to be using:

// app.module.ts...
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import {
MatButtonModule,
MatInputModule,
MatFormFieldModule,
MatProgressSpinnerModule,
MatCardModule,
MatRippleModule
} from '@angular/material';
@NgModule({
...
imports: [
...
BrowserAnimationsModule,
MatButtonModule
MatFormFieldModule,
MatInputModule,
MatCardModule,
MatProgressSpinnerModule,
MatRippleModule,
],
...
})
export class AppModule { }

Now we can add a prebuilt material theme to our “styles.scss” file. And while we’re here let’s just add some standard “body” styles:

// styles.scss@import "~@angular/material/prebuilt-themes/indigo-pink.css";body {
margin: 0;
font-family: 'Roboto', sans-serif;
}

[Or if you’d like to add a custom theme go ahead and check out the angular material docs https://material.angular.io/guide/theming#defining-a-custom-theme]

It’s always useful to add material icons too, over in “index.html”:

// index.html<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

2. Done Setting Up! Now Let’s Talk Routing

Create Routes

Now that’s all out the way we get to the fun stuff. We’re now going to set up our routing. When no path is provided we will try to redirect to “/home”, you will see that this route has AuthGuard checking if the route can load. The AuthGuard redirects the user to the register page when the user is not logged in, we’ll come to this soon.

The Auth route is set up so that “/auth/login” will display login and “/auth/register” will display register. This way later on we can use AuthComponent’s template to render it’s child components (register and login) within an Angular Material “Card”.

For ease and simplicity let’s add the routes just under imports in app.module.ts:

// app.module.ts...
import { Routes } from '@angular/router';
import { AuthGuard } from './auth/auth.guard';
const routes: Routes = [
{ path: '', pathMatch: 'full', redirectTo: 'home'},
{ path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
{
path: 'auth',
component: AuthComponent,
children: [
{ path: '', pathMatch: 'full', redirectTo: 'register' },
{ path: 'register', component: RegisterComponent },
{ path: 'login', component: LoginComponent }
]
}
];

And tell RouterModule about these routes:

// app.module.tsimport { RouterModule, Routes } from '@angular/router';@NgModule({
...
imports: [
...
RouterModule.forRoot(routes)
],
providers: [AuthGuard],
...
})
export class AppModule { }

Now we need to tell Angular where to render the routes by rendering “<router-outlet>”s in html.

Over in “app.component.html” remove all existing code and replace with:

// app.component.html<router-outlet></router-outlet>

And finally in “auth.component.hmtl”:

// auth.component.html<router-outlet></router-outlet>

This is where our AuthComponent child routes will be rendered — “/auth/signup” and “/auth/login”.

AuthGuard — Protect Home

Here we’re making use of the AuthService we created right at the start, we haven’t written the code for “this.authService.isAuthenticated” yet, but we will come to this next.

We’re checking if the user is authenticated, if they are then we return true, this allows the user access to the route that the AuthGuard is guarding. If not, then we redirect them to ‘/auth/register’.

// auth.guard.tsimport { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
import { Observable } from 'rxjs';
import { AuthService } from './auth.service';
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authService: AuthService) {}
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
if (this.authService.isAuthenticated) { return true; }
this.router.navigate(['/auth/register']);
return false;
}
}

AuthService — The Code For Checking If Authorised

We use AngularFireAuth to subscribe to the authState in the constructor, this means every time the user logs in or out our code is ran, and we update the private “_isAuthenticated” property to true (when the user is logged in) or false (when the user is not logged in). The get isAuthenticated() method is used in the AuthGuard we just created to allow access to the private _isAuthenticated property.

// auth.service.tsimport { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { Router } from '@angular/router';
@Injectable({
providedIn: 'root'
})
export class AuthService {
private _isAuthenticated: boolean = null;
public get isAuthenticated(): boolean {
return this._isAuthenticated;
}
constructor(private afAuth: AngularFireAuth) {
afAuth.authState.subscribe(user => this._isAuthenticated = !!user);
}
}

… Coming In The Next Post

We’re going to be fixing up the login and register functionality in the next episode, and also putting together the styles!

Thanks for reading, talk soon

— AP

--

--