Setting up Material Design with Angular 6

Spread the love
  • 9
    Shares

Material Design started in 2014 and it was introduced by Google to provide a consistent look and feel across browsers. It combines animation effects with soothing colors, shadows, aptly measured margins/padding etc to improve the User experience. Back in the era of Flash/Flex, components designed using Flex has a visual appearance which felt natural. Without any need of adding styles, the plain Flex User Interface felt good. HTML components were lacking such natural appearance. Maintaining consistency across the browser was always a pain. With Material Design the UI aesthetics and interaction has improved dramatically.

Though Angular CLI enables you to quickly get started with creating a new project, it doesn’t come bundled with the Material design. Additional steps are required to integrate the Material Design and apply the styling to the components. In this article, we will learn the steps to integrate Material Design in Angular 6. We will extend this article and build following UI to understand some of the Material Design Components.

Angular Material

Angular Material

Prerequisites

Before we begin, make sure that you have following softwares installed on your machine

Generate Template Project

With Angular CLI it is very easy to generate a new project. Go to the command prompt or terminal and type following command

ng new angularmaterial

The command will create a new Angular project with default module and component. It will also download the required dependencies. The execution of the command may take some time depending on the internet speed you have. Once the command is complete, switch to the angularmaterial directory and enter the following command to verify the application

ng serve

This will start compiling the modules using webpack and host the application using internal HTTP server. The application will be hosted on port 4200. Open the browser and enter the following URL

http://localhost:4200

You should see a welcome message with Angular logo.

Web Page without Material Design

Let us create a component with the default look and feel and we will then create a similar replica of it with Material Design. This will help us to identify the difference between the pages. To generate a new component, enter the following command at the root of the project

ng generate component plain

A new directory plain will be created under src\app. The command will also create default template HTML, typescript, style (css) and test file for the component. Open plain.component.html file and replace the content with following

Sign Up!!!
<br/><br/>

<form>
<div>
First Name: <input type="text" name="firstName" />
</div>
<div>
Last Name: <input type="text" name="lastName" />
</div>
<div>
Gender: <input type="radio" name="gender" value="male" /> Male &nbsp;
<input type="radio" name="gender" value="female" /> Female
</div>
<div>
Email: <input type="email" name="email" />
</div>
<div>
Address: <textarea name="address" rows="3" cols="30"></textarea>
</div>
<div>
Area of Interest: <select name="areaInterest">
<option *ngFor="let interest of interests" [value]="interest.value">
{{interest.viewValue}}
</option>
</select>
</div>
<div>
<button type="submit">REGISTER</button>
</div>
</form>

We have used default HTML controls to design our form. For demonstration purpose, we have used various controls like text input, radio, text area, select and button. To populate the select options, open plain.component.ts file and replace it with following code.

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



@Component({
  selector: 'plain-component-app',
  templateUrl: './plain.component.html',
  styleUrls: [ './plain.component.css' ]
})
export class PlainComponent implements OnInit {
  interests = [];

  ngOnInit() {
    this.interests = [
      {value:'reading', viewValue:'Reading'},
      {value:'swimming', viewValue:'Swimming'},
      {value:'cycling', viewValue:'Cycling'}
    ];
  }
}

Router for displaying module

The page we have just created will not be visible immediately. Also, we will not directly embed it in the main application module. Instead of that, we will use a router to load the page. This will give us the option to switch between default HTML page and one designed with Material Design.

Open src\app\app.component.html and replace its content with following

 
<div>
<button (click)="showPlainPage()">Plain Page</button> &nbsp;
<button (click)="showMaterialPage()">Material Page</button>
</div>
<br/>
<router-outlet></router-outlet>

Read the HTML content carefully, we have used router-outlet tag to define a placeholder. It will be used to load the component we have defined. Now replace the content of src\app\app.component.ts with following

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

import { Router } from '@angular/router';


@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  constructor(private router: Router) {

  }
  showPlainPage() {
    this.router.navigate(['plain']);
  }

  showMaterialPage() {
    this.router.navigate(['material']);
  }
}

The route definition needs to be registered and the router module should be imported to make it available for the components. Modify the src\app\app.module.ts with following contents.

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';
import { PlainComponent } from './plain/plain.component';

const appRoutes: Routes = [
  { path: 'plain', component: PlainComponent }
];

@NgModule({
  imports: [BrowserModule, FormsModule, BrowserAnimationsModule,
    RouterModule.forRoot(
      appRoutes,
      {
        enableTracing: true
      })],
  declarations: [AppComponent, PlainComponent],
  bootstrap: [AppComponent],
  exports: [ RouterModule]
})
export class AppModule { }

We have imported RouterModule and Routes from @angular/router. Constant appRoutes has been defined, to map components with URL fragments. Also to enable detailed logging, we have configured option enableTracing for RouterModule.forRoot call. Type following command at the command prompt and visit browser URL – http://localhost:4200. Click button Plain Page and you should have the following page

Plain Angular

Plain Angular

The page looks pretty simple and has no formatting at all. We will change the look and feel of the page using Material Design.

Installing Material Dependencies

As stated earlier the Material Design Components does not come bundled with default angular project. We will have to install it using the following command

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

We will create new module – withmaterial. This will have an exact replica of the component we just now designed with Material components

Material Design Components

To create new component, enter following command

ng generate component withmaterial

You will now have new component under src\app\withmaterial. Let’s define Material components in the HTML file. Copy following code and overwrite it in withmaterial.component.html

<mat-toolbar>
Sign Up!!!
</mat-toolbar>

<form>
<div>
<mat-form-field>
<input type="text" matInput name="firstName" placeholder="First Name" />
</mat-form-field>
</div>
<div>
<mat-form-field>
<input type="text" matInput name="lastName" placeholder="Last Name" />
</mat-form-field>
</div>
<div>
<mat-radio-group>
<mat-radio-button name="gender" value="male"> Male </mat-radio-button> &nbsp;
<mat-radio-button name="gender" value="female"> Female </mat-radio-button>
</mat-radio-group>
</div>
<div>
<mat-form-field>
<input matInput type="email" name="email" placeholder="Email" />
</mat-form-field>
</div>
<div>
<mat-form-field>
<textarea matInput name="address" rows="3" cols="30" placeholder="address"></textarea>
</mat-form-field>
</div>
<div>
<mat-form-field>
<mat-select name="areaInterest" placeholder="Area of Interest:">
<mat-option *ngFor="let interest of interests" [value]="interest.value">
{{interest.viewValue}}
</mat-option>
</mat-select>
</mat-form-field>
</div>
<div>
<button mat-raised-button color="primary" type="submit">REGISTER</button>
</div>
</form>

After careful observation of the above code, you will realize that

  1. All input fields are wrapped inside <mat-form-field>. The fields are also tagged with attribute matInput
  2. Radio buttons are wrapped inside <mat-radio-group>
  3. Select and Option has been replaced with <mat-select> and <mat-option>.
  4. Button tag has an additional attibute mat-raised-button.

To populate the select option, replace withmaterial.component.ts with following contents

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

@Component({
  selector: 'with-material-app',
  templateUrl: './withmaterial.component.html',
  styleUrls: [ './withmaterial.component.css' ]
})
export class WithMaterialComponent implements OnInit  {
  interests = [];

  ngOnInit() {
    this.interests = [
      {value:'reading', viewValue:'Reading'},
      {value:'swimming', viewValue:'Swimming'},
      {value:'cycling', viewValue:'Cycling'}
    ];
  }

}

Import Material Design Modules

To use Material design components, we must include the respective modules in our main module. Open src\app\app.module.ts and replace it with following contents

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { MatButtonModule, MatInputModule, MatFormFieldModule, MatRadioModule, MatSelectModule, MatToolbarModule } from '@angular/material';
import { RouterModule, Routes } from '@angular/router';

import { AppComponent } from './app.component';
import { WithMaterialComponent } from './withmaterial/withmaterial.component';
import { PlainComponent } from './plain/plain.component';

const appRoutes: Routes = [
  { path: 'plain', component: PlainComponent },
  { path: 'material', component: WithMaterialComponent }
];

@NgModule({
  imports: [BrowserModule, FormsModule, MatButtonModule, MatFormFieldModule, MatInputModule, MatRadioModule, MatSelectModule, MatToolbarModule, BrowserAnimationsModule,
    RouterModule.forRoot(
      appRoutes,
      {
        enableTracing: true
      })],
  declarations: [AppComponent, WithMaterialComponent, PlainComponent],
  bootstrap: [AppComponent],
  exports: [ RouterModule]
})
export class AppModule { }

In above code we have imported MatButtonModule, MatFormFieldModule, MatInputModule, MatRadioModule, MatSelectModule, MatToolbarModule from @angular\material. Same has been specified in imports property for @NgModule.

BrowserAnimationsModule has been imported to enable animation for Material components. Angular provides an option to disable animation using NoopAnimationsModule.

Constant appRoutes has been extended to include path for the new material component. Now its time to include material specific style. Open src\styles.css file and add the following line to it.

@import "[email protected]/material/prebuilt-themes/indigo-pink.css";

The material design comes with various prebuilt themes to choose from.

If ng serve command is running, refresh the browser and you should have following output for the Material page.

Angular Material

Angular Material

Congratulations!!! we have successfully integrated material design with Angular. What we have explored is just a few basic options of material design. If you are interested in exploring more capabilities of Material and other components visit Official Angular Material website.

The entire source code can be viewed at

Leave a Comment.