{{announcement.body}}
{{announcement.title}}

Create a Beautiful Login Form With Angular Material

DZone 's Guide to

Create a Beautiful Login Form With Angular Material

This Angular Material tutorial will help you craft a great login form that includes single sign-on capabilities, provided by Okta in this example.

· Web Dev Zone ·
Free Resource

Creating a clean, intuitive user interface is a key part of designing web applications. This has historically been challenging, however, because web apps don’t have a common design language like desktop apps do.

Enter Material Design. Google released Material Design in 2014 with the goal of creating a common user experience across Android devices and web apps. Material design has components that developers can use for both Android and JavaScript applications.

Material Design has become very popular. Developers have created libraries that incorporate Material Design components into existing frameworks. Within Angular applications, you can use the angular-material library, which makes all Material components available for your Angular templates. The catch is that you use Material Design in your application, you should be sure to use it across all parts of your app—it’s a common design language, after all. 

As you’re building your next app, you may want to use a single sign-on service like Okta. In its default configuration, Okta redirects users to a hosted login page and redirects them back to the app when they sign in successfully. If you’re using Material Design with your application, you might want to create your own login form to match the rest of your app, but you can still do this with Okta!

In this tutorial, I’ll show you how to create a login form like the one above. You’ll create an Angular app, use Material Design, and make it require user login. Okta provides a library specifically for Angular applications but I will be using the more low-level okta-auth-js library. This library allows you to have full control over your HTML and just handles communication with Okta’s API. All of Okta’s JavaScript libraries are built on top of okta-auth-js. To make the application a bit more interesting, I will be creating a small tic-tac-toe game that will be protected using Okta for authentication.

Build an Angular Material App with Secure Login

To get started, you will need to install the Angular command-line tool. I will assume that you have some familiarity with JavaScript and that you have Node installed on your system together with the Node Package Manager npm. Open a terminal and type the following command.

Shell
 




x


1
npm install -g @angular/cli@8.3.21


Depending on your operating system, you might have to run this using the sudo command. This will install the Angular command-line tool on your system. It lets you use the ng command to set up and manipulate Angular applications. To create a new application navigate to a directory of your choice and run the following.

Shell
 




xxxxxxxxxx
1


 
1
ng new material-tic-tac-toe


You will be asked two questions. Answer Yes to the first question. This will include and set up the router in your application. The router is responsible for letting the user navigate between different parts of the app and updating the browser’s URL without actually reloading the page. For the second question, accept the default choice CSS. This application will use simple CSS stylesheets but you can see how easy it is to switch to a different stylesheet technology with Angular.

Once the wizard has completed you should see a new folder called material-tic-tac-toe. Navigate into the folder and install some packages you will need for the application by running the command below.

Shell
 




xxxxxxxxxx
1


 
1
npm install -E @angular/material@8.2.3 @angular/flex-layout@8.0.0-beta.27 hammerjs@2.0.8 @angular/cdk@8.2.3 tic-tac-toe-minimax@1.0.8


The @angular/material package provides the components of the Material Design, @angular/cdk is a component development kit that is needed for the Material components to work and hammerjs is a library that provides smooth animations for the component. @angular/flex-layout provides a flexible and responsive grid. It is independent of the Material components but is often used together with it. Finally, tic-tac-toe-minimax is a ready-to-go tic-tac-toe game with a computer player.

Add Angular Material CSS

The Material components do not include the web-font for the Material Icon set. In order to use the icons, open src/index.html in your IDE and add the following line inside the <head> tag.

HTML
 




xxxxxxxxxx
1


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


To make hammerjs available to the application open src/main.ts and add the following import to the top of the file.

Shell
 




xxxxxxxxxx
1


 
1
import 'hammerjs';


Next, add the Material Design stylesheet to your application. Open src/styles.css and paste the code below into the file.

CSS
 




xxxxxxxxxx
1
10


 
1
@import "~@angular/material/prebuilt-themes/deeppurple-amber.css";
2
 
          
3
body {
4
  margin: 0;
5
  font-family: sans-serif;
6
}
7
 
          
8
h1 {
9
  text-align: center;
10
}


The @import statement imports a pre-built theme into the CSS file. I have also added a bit of styling for the body and h1 elements. Next, you need to import all the modules you will be needing into the application.

Import Angular Material Components

Open src/app/app.module.ts and add the imports below to the top of the file.

Java
 




xxxxxxxxxx
1
16


 
1
import { FlexLayoutModule } from '@angular/flex-layout';
2
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
3
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
4
 
          
5
import { MatToolbarModule,
6
         MatMenuModule,
7
         MatIconModule,
8
         MatButtonModule,
9
         MatTableModule,
10
         MatDividerModule,
11
         MatProgressSpinnerModule,
12
         MatInputModule,
13
         MatCardModule,
14
         MatSlideToggleModule,
15
         MatSelectModule,
16
         MatOptionModule} from '@angular/material';


Now scroll down in the same file and find the imports declaration. Change it to match the following.

CSS
 




xxxxxxxxxx
1
20


 
1
imports: [
2
  BrowserModule,
3
  AppRoutingModule,
4
  FlexLayoutModule,
5
  FormsModule,
6
  ReactiveFormsModule,
7
  BrowserAnimationsModule,
8
  MatToolbarModule,
9
  MatInputModule,
10
  MatCardModule,
11
  MatMenuModule,
12
  MatIconModule,
13
  MatButtonModule,
14
  MatTableModule,
15
  MatDividerModule,
16
  MatSlideToggleModule,
17
  MatSelectModule,
18
  MatOptionModule,
19
  MatProgressSpinnerModule
20
],


Now that you’re done with all the preliminaries, it’s time to start implementing the game application.

Build a Gameboard with Angular Material

Start with the main application component. Open src/app/app.component.html and replace the default contents with the following code.

HTML
 




xxxxxxxxxx
1
42


 
1
<mat-toolbar color="primary" class="expanded-toolbar">
2
    <span>
3
      <button mat-button routerLink="/">{{title}}</button>
4
      <button mat-button routerLink="/"><mat-icon>home</mat-icon></button>
5
    </span>
6
  <div fxLayout="row" fxShow="false" fxShow.gt-sm>
7
    <button mat-button routerLink="/login" *ngIf="!isAuthenticated">
8
      <mat-icon>power_settings_new</mat-icon>
9
      Login
10
    </button>
11
    <button mat-button *ngIf="isAuthenticated" (click)="logout()">
12
      <mat-icon>exit_to_app</mat-icon>
13
      Logout
14
    </button>
15
    <button mat-button routerLink="/game">
16
      <mat-icon>gamepad</mat-icon>
17
      Play
18
    </button>
19
  </div>
20
  <button mat-button [mat-menu-trigger-for]="menu" fxHide="false" fxHide.gt-sm>
21
    <mat-icon>menu</mat-icon>
22
  </button>
23
</mat-toolbar>
24
<mat-menu x-position="before" #menu="matMenu">
25
  <button mat-menu-item routerLink="/">
26
    <mat-icon>home</mat-icon>
27
    Home
28
  </button>
29
  <button mat-menu-item routerLink="/game">
30
    <mat-icon>gamepad</mat-icon>
31
    Play
32
  </button>
33
  <button mat-menu-item routerLink="/login" *ngIf="!isAuthenticated">
34
    <mat-icon>power_settings_new</mat-icon>
35
    Login
36
  </button>
37
  <button mat-menu-item *ngIf="isAuthenticated" (click)="logout()">
38
    <mat-icon>exit_to_app</mat-icon>
39
    Logout
40
  </button>
41
</mat-menu>
42
<router-outlet></router-outlet>


This code contains the main toolbar and menu of the application. Only a small amount of styling is needed. Paste the following into src/app/app.component.css.

CSS
 




xxxxxxxxxx
1


 
1
.expanded-toolbar {
2
  justify-content: space-between;
3
  align-items: center;
4
}


Now, open src/app/app.component.ts and modify the component title and add an isAuthenticated property. The contents of the file should look like this.

CSS
 




xxxxxxxxxx
1
11


 
1
import { Component } from '@angular/core';
2
 
          
3
@Component({
4
  selector: 'app-root',
5
  templateUrl: './app.component.html',
6
  styleUrls: ['./app.component.css']
7
})
8
export class AppComponent {
9
  title = 'Tic Tac Toe';
10
  isAuthenticated: boolean;
11
}


Open your terminal again and create two components home, and game by running the commands below.

Shell
 




xxxxxxxxxx
1


 
1
ng generate component home
2
ng generate component game


The home component simply contains a splash screen with the game title. Replace the contents of src/app/home/home.component.html with the following line.

HTML
 




xxxxxxxxxx
1


 
1
<h1>Tic Tac Toe</h1>


The game component will need a bit more editing. Start with the template and open src/app/game/game.component.html. Replace the contents of the file with the following code.

HTML
 




xxxxxxxxxx
1
32


 
1
<mat-card>
2
  <mat-card-content>
3
    <div [ngClass]="{'tic-tac-toe': true, playing: playing}">
4
      <div class="game-field" *ngFor="let field of gameState; let i = index" (click)="makeHumanMove(i)">
5
        {{field === 'X' || field === 'O' ? field : ''}}
6
      </div>
7
    </div>
8
  </mat-card-content>
9
</mat-card>
10
<mat-card>
11
  <mat-card-content>
12
    <div *ngIf="playing">
13
        <h3>Your Move</h3>
14
    </div>
15
    <div *ngIf="!playing">
16
        <h3>{{winner || "Start a new game"}}</h3>
17
    </div>
18
    <button mat-raised-button color="primary" *ngIf="!playing" (click)="toggleGame(true)">Start</button>
19
    <button mat-raised-button color="primary" *ngIf="playing" (click)="toggleGame(false)">Reset</button>
20
 
          
21
    <mat-slide-toggle [(ngModel)]="computerFirst">Computer Moves First</mat-slide-toggle>
22
 
          
23
    <mat-form-field>
24
      <mat-label>Difficulty</mat-label>
25
      <mat-select [(ngModel)]="difficulty">
26
        <mat-option value="Easy">Easy</mat-option>
27
        <mat-option value="Normal">Normal</mat-option>
28
        <mat-option value="Hard">Hard</mat-option>
29
      </mat-select>
30
    </mat-form-field>
31
  </mat-card-content>
32
</mat-card>


The code above defined two cards. The top card contains the current game state. It also lets the user click on any of the fields to make a move. The bottom card contains the game controls. Add some styling by pasting the following code into src/app/game/game.component.css.

CSS
 




xxxxxxxxxx
1
36


 
1
mat-card {
2
  max-width: 400px;
3
  margin: 2em auto;
4
  text-align: center;
5
}
6
 
          
7
mat-card-content {
8
  display: flex;
9
  flex-direction: column;
10
  justify-content: center;
11
  align-items: center;
12
}
13
 
          
14
.tic-tac-toe {
15
  width: 192px;
16
  display: flex;
17
  flex-wrap:  wrap;
18
}
19
 
          
20
.game-field {
21
  width: 48px;
22
  height: 48px;
23
  margin: 8px;
24
  background-color: #f0f0f0;
25
  line-height: 48px;
26
  font-size: 32px;
27
  font-weight: bold;
28
}
29
 
          
30
.playing .game-field {
31
  cursor: pointer;
32
}
33
 
          
34
button, mat-slide-toggle {
35
  margin-bottom: 2rem;
36
}


Implement Your Game Logic With Angular Components

The actual game logic lives in src/app/game/game.component.ts. It is using the tic-tac-toe-minimax library to calculate computer moves and determine the winner. Replace the contents of the file with the code below.

CSS
 




xxxxxxxxxx
1
68


 
1
import { Component, OnInit } from '@angular/core';
2
import Minimax from 'tic-tac-toe-minimax';
3
const { GameStep } = Minimax;
4
 
          
5
@Component({
6
  selector: 'app-game',
7
  templateUrl: './game.component.html',
8
  styleUrls: ['./game.component.css']
9
})
10
export class GameComponent implements OnInit {
11
 
          
12
  public gameState: Array<number | string> = [0, 1, 2, 3, 4, 5, 6, 7, 8];
13
  public winner: string;
14
  public playing = false;
15
  public computerFirst = false;
16
  public difficulty: 'Easy'|'Normal'|'Hard' = 'Normal';
17
 
          
18
  constructor() {}
19
 
          
20
  ngOnInit() {
21
  }
22
 
          
23
  toggleGame(toggle: boolean) {
24
    if (toggle === this.playing) {
25
      return;
26
    }
27
 
          
28
    this.gameState = [0, 1, 2, 3, 4, 5, 6, 7, 8];
29
    this.winner = undefined;
30
 
          
31
    if (toggle && this.computerFirst) {
32
      this.makeComputerMove();
33
    }
34
 
          
35
    this.playing = toggle;
36
  }
37
 
          
38
  makeComputerMove() {
39
    const symbols = {
40
      huPlayer: 'X',
41
      aiPlayer: 'O'
42
    };
43
 
          
44
    const winnerMapping = {
45
      huPlayer: 'Human Wins!',
46
      aiPlayer: 'Computer Wins!',
47
      draw: 'It\'s a Draw!'
48
    };
49
 
          
50
    const result = GameStep(this.gameState, symbols, this.difficulty);
51
    this.gameState = result.board;
52
 
          
53
    if (result.winner) {
54
      this.winner = winnerMapping[result.winner];
55
      this.playing = false;
56
    }
57
  }
58
 
          
59
  makeHumanMove(field: number) {
60
    if (!this.playing || typeof this.gameState[field] !== 'number') {
61
      return;
62
    }
63
 
          
64
    this.gameState[field] = 'X';
65
    this.makeComputerMove();
66
  }
67
 
          
68
}


To complete the game, you will need to define the routes to the two components.

Add Routes to Your Angular Components

Open src/app/app-routing.module.ts and add the following imports to the top of the file.

TypeScript
 




xxxxxxxxxx
1


 
1
import { HomeComponent } from './home/home.component';
2
import { GameComponent } from './game/game.component';


Next, change the routes array to match the following.

TypeScript
 




xxxxxxxxxx
1
10


 
1
const routes: Routes = [
2
  {
3
    path: '',
4
    component: HomeComponent
5
  },
6
  {
7
    path: 'game',
8
    component: GameComponent,
9
  },
10
];


This completes the implementation of the game. You should now be able to open a terminal and run the following command:

Shell
 




xxxxxxxxxx
1


 
1
ng serve


Open your browser and navigate to http://localhost:4200. Click on the Play link in the top menu and you should see a fully functional tic-tac-toe game. Note that the Login link is not yet wired up. If you click on it nothing will happen and you can see an error message in the browser’s console.

Add Secure Sign In to Your Angular App

Before you can start implementing the login page you need to register with Okta. Creating an account is simple and free. Just open a browser and navigate to https://developer.okta.com. Click Create Free Account and complete the registration process.

When you are done you will be redirected to your Okta developer dashboard. Register a new application by going to Applications > Add Application. On the next screen, choose Single Page App and click Next.

On the following screen, you can edit the application’s settings. Make sure that the port number is 4200 and the base URI is http://localhost:4200/. Change the Login Redirect URI to http://localhost:4200/login. Once you are done, you should now see a Client ID which you will need later in your code.

You will be implementing a login form as part of your application. Before continuing, a few warnings. If you decide to run a production environment in which you host your own login form, make sure that you are using the secure HTTPS protocol and you are hosting your site with a valid SSL certificate. Also, make sure to never store the login data in a session variable or the browser’s storage. If you fail to take the necessary security precautions, your site may be vulnerable to attacks. As mentioned above, you will not be using any of the Angular-specific Okta libraries. Instead, install the okta-auth-js package by opening the terminal in the project’s root folder and typing the following command.

Shell
 




xxxxxxxxxx
1


 
1
npm install -E @okta/okta-auth-js@2.11.0


With this, you are ready to create the authentication service. In the terminal, type the following command.

Shell
 




xxxxxxxxxx
1


 
1
ng generate service Auth


Now open the newly created file src/app/auth.service.ts. This file is where all the magic happens. Paste the following contents into the file. I will walk you through the code step-by-step below.

TypeScript
 




xxxxxxxxxx
1
46


 
1
import { Injectable } from '@angular/core';
2
import { BehaviorSubject } from 'rxjs';
3
import { Router } from '@angular/router';
4
import OktaAuth from '@okta/okta-auth-js';
5
 
          
6
@Injectable({
7
  providedIn: 'root'
8
})
9
export class AuthService {
10
  private authClient = new OktaAuth({
11
    issuer: 'https://{YourOktaDomain}/oauth2/default',
12
    clientId: '{ClientId}'
13
  });
14
 
          
15
  public isAuthenticated = new BehaviorSubject<boolean>(false);
16
 
          
17
  constructor(private router: Router) {
18
  }
19
 
          
20
  async checkAuthenticated() {
21
    const authenticated = await this.authClient.session.exists();
22
    this.isAuthenticated.next(authenticated);
23
    return authenticated;
24
  }
25
 
          
26
  async login(username: string, password: string) {
27
    const transaction = await this.authClient.signIn({username, password});
28
 
          
29
    if (transaction.status !== 'SUCCESS') {
30
      throw Error('We cannot handle the ' + transaction.status + ' status');
31
    }
32
    this.isAuthenticated.next(true);
33
 
          
34
    this.authClient.session.setCookieAndRedirect(transaction.sessionToken);
35
  }
36
 
          
37
  async logout(redirect: string) {
38
    try {
39
      await this.authClient.signOut();
40
      this.isAuthenticated.next(false);
41
      this.router.navigate([redirect]);
42
    } catch (err) {
43
      console.error(err);
44
    }
45
  }
46
}


The AuthService defines a member authClient that is initialized to be an OktaAuth object. This object encapsulates the authentication, session management, and communication with the Okta servers. The OktaAuth constructor takes several options. The options provided here are the issuer and the clientId. In these options, you will have to replace {YourOktaDomain} with your Okta domain that you can find on the Okta dashboard. The {ClientId} needs to be replaced with the client ID you obtained when you registered your application with Okta.

The isAuthenticated property is a behavior subject that reflects whether the user is logged in or not. The AuthService also defines three asynchronous methods. The checkAuthenticated() method checks whether a user session exists and returns the outcome. It also updates the isAuthenticated subject. The login() method sends a sign-in request to the Okta server. On success, the user is authenticated and a session is established. The logout() method will sign out the user and redirect them to a specified route.

Now that the service is in place, you can use it in the application component. Open src/app/app.component.ts and modify the contents to match the code below.

TypeScript
 




xxxxxxxxxx
1
26


 
1
import { Component, OnInit } from '@angular/core';
2
import { AuthService } from './auth.service';
3
 
          
4
@Component({
5
  selector: 'app-root',
6
  templateUrl: './app.component.html',
7
  styleUrls: ['./app.component.css']
8
})
9
export class AppComponent implements OnInit {
10
  title = 'Tic Tac Toe';
11
  isAuthenticated: boolean;
12
 
          
13
  constructor(public authService: AuthService) {
14
    this.authService.isAuthenticated.subscribe(
15
      (isAuthenticated: boolean)  => this.isAuthenticated = isAuthenticated
16
    );
17
  }
18
 
          
19
  async ngOnInit() {
20
    this.isAuthenticated = await this.authService.checkAuthenticated();
21
  }
22
 
          
23
  logout() {
24
    this.authService.logout('/');
25
  }
26
}


The isAuthenticated variable is now initialized and updated by the authentication service. And the logout() method will sign the user out and redirect them to the home page.

Now create the login component. In the terminal, run the command below.

Shell
 




xxxxxxxxxx
1


 
1
ng generate component login


Open src/app/login/login.component.html and add the following login form.

HTML
 




xxxxxxxxxx
1
23


 
1
<mat-card>
2
  <mat-card-content>
3
    <form [formGroup]="form" (ngSubmit)="onSubmit()">
4
      <h2>Log In</h2>
5
      <mat-error *ngIf="loginInvalid">
6
        The username and password were not recognised
7
      </mat-error>
8
      <mat-form-field class="full-width-input">
9
        <input matInput placeholder="Email" formControlName="username" required>
10
        <mat-error>
11
          Please provide a valid email address
12
        </mat-error>
13
      </mat-form-field>
14
      <mat-form-field class="full-width-input">
15
        <input matInput type="password" placeholder="Password" formControlName="password" required>
16
        <mat-error>
17
          Please provide a valid password
18
        </mat-error>
19
      </mat-form-field>
20
      <button mat-raised-button color="primary">Login</button>
21
    </form>
22
  </mat-card-content>
23
</mat-card>


Everything is contained in a <mat-card> element again. Note how the <mat-form-field> elements each contain an <input> as well as a <mat-error> element. The <mat-error> works seamlessly with Angular’s form validation to provide useful feedback. As you might have guessed by now, src/app/login/login.component.css contains some styling. Paste the code below into the file.

CSS
 




xxxxxxxxxx
1


 
1
mat-card {
2
  max-width: 400px;
3
  margin: 2em auto;
4
  text-align: center;
5
}
6
 
          
7
mat-form-field {
8
  display: block;
9
}


Now open src/app/login/login.component.ts and paste in the implementation of the login component.

TypeScript
 




xxxxxxxxxx
1
53


 
1
import { Component, OnInit } from '@angular/core';
2
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
3
import { ActivatedRoute, Router } from '@angular/router';
4
import { AuthService } from '../auth.service';
5
 
          
6
@Component({
7
  selector: 'app-login',
8
  templateUrl: './login.component.html',
9
  styleUrls: ['./login.component.css']
10
})
11
export class LoginComponent implements OnInit {
12
  form: FormGroup;
13
  public loginInvalid: boolean;
14
  private formSubmitAttempt: boolean;
15
  private returnUrl: string;
16
 
          
17
  constructor(
18
    private fb: FormBuilder,
19
    private route: ActivatedRoute,
20
    private router: Router,
21
    private authService: AuthService
22
  ) {
23
  }
24
 
          
25
  async ngOnInit() {
26
    this.returnUrl = this.route.snapshot.queryParams.returnUrl || '/game';
27
 
          
28
    this.form = this.fb.group({
29
      username: ['', Validators.email],
30
      password: ['', Validators.required]
31
    });
32
 
          
33
    if (await this.authService.checkAuthenticated()) {
34
      await this.router.navigate([this.returnUrl]);
35
    }
36
  }
37
 
          
38
  async onSubmit() {
39
    this.loginInvalid = false;
40
    this.formSubmitAttempt = false;
41
    if (this.form.valid) {
42
      try {
43
        const username = this.form.get('username').value;
44
        const password = this.form.get('password').value;
45
        await this.authService.login(username, password);
46
      } catch (err) {
47
        this.loginInvalid = true;
48
      }
49
    } else {
50
      this.formSubmitAttempt = true;
51
    }
52
  }
53
}


There is not much happening here. ngOnInit() sets up the form. If the user is already authenticated it requests the router to navigate to a different URL. The onSubmit() function handles the form submission. It extracts the values from the form elements and attempts to log in using AuthService.

The application is almost done. You have the authentication service and the login form in place. But you also want to prevent the user from navigating to a part of the application that they are not authorized to see. Angular uses route guards for this. Create a new service by running the following command in the terminal.

Shell
 




xxxxxxxxxx
1


 
1
ng generate service AuthGuard


The guard implements the CanActivate interface and must implement the canActivate() function. Replace the contents of src/app/auth-guard.service.ts with the following.

TypeScript
 




xxxxxxxxxx
1
19


 
1
import { Injectable } from '@angular/core';
2
import { Router, CanActivate } from '@angular/router';
3
import { AuthService } from './auth.service';
4
 
          
5
@Injectable({
6
  providedIn: 'root'
7
})
8
export class AuthGuardService implements CanActivate {
9
 
          
10
  constructor(public authService: AuthService, public router: Router) {}
11
 
          
12
  async canActivate() {
13
    if (!await this.authService.checkAuthenticated()) {
14
      await this.router.navigate(['login']);
15
      return false;
16
    }
17
    return true;
18
  }
19
}


Finally, add the login route and the route guard to the router setup. Open src/app/app-routing.module.ts again and add the two imports below.

TypeScript
 




xxxxxxxxxx
1


 
1
import { LoginComponent } from './login/login.component';
2
import { AuthGuardService } from './auth-guard.service';


Now, change the routes array to look like the following.

TypeScript
 






Well done, that’s it. The application is complete!

When you run the ng serve command and navigate to http://localhost:4200 you should now be able to log in and out of the application. The login form uses Material Design and should look something like the image below.

Make Angular Tests Pass With Angular Material

You generated a lot of code in this tutorial. When you created components, tests were created for those components as well. The tests merely verify the components render. If you run ng test, most of them will fail because the tests don’t have the imports for the components you added. If you’d like to see what it takes to make all the tests pass, see this commit.

Learn More About Angular Material and Secure Login

In this tutorial, I showed you how to implement your own login form in an Angular application using Material Design and the Angular Material library. Coding up your own form may be a viable option if you want to present a uniform user experience. Much of this tutorial can be used for other design libraries and is not limited to Material Design but Google’s Material Design standard is probably one of the most recognized user interface standards nowadays. Using it will improve the usability of your web application.

You can download the code for this tutorial from oktadeveloper/okta-angular-material-login-example.

If you want to learn more about Angular, Material Design, or ways to use Okta with Angular, feel free to check out the links below.

As usual, follow us @oktadev on Twitter and subscribe to our YouTube channel for more excellent content!

Topics:
angular, angular material, login, material design, single sign-on, web dev

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}