How to Use Angular CDK

How to Use Angular CDK

In this post, I am going to show you how to create a reusable modal overlay/dialog using Angular CDK Overlay that can be reused inside our Angular project multiple times with ease. We are going to try and match the behavior and the functionality of Angular Material Dialog component, but using the UI Framework of our choice.

In this post, I am going to show you how to create a reusable modal overlay/dialog using Angular CDK Overlay that can be reused inside our Angular project multiple times with ease. We are going to try and match the behavior and the functionality of Angular Material Dialog component, but using the UI Framework of our choice.

Prerequisites

  • Install Angular CLI and create a new Angular project – link.

  • Setup Bulma inside your Angular Project.

  • Install Angular CDK – npm i @angular/cdk or yarn add @angular/cdk

The article is divided into two sections:

  • The Basics - a Quick look at how to use Angular CDK Overlay
  • Building a Reusable Modal Overlay - A detailed guide into building a reusable modal overlay.

The Basics

Let us get the basics out of the way first. Assuming you have installed Angular CDK you will need to import OverlayModule into your app module.

import {OverlayModule} from '@angular/cdk/overlay';

And then, inject the Overlay service and ViewContainerRef into your component.

constructor(private overlay: Overlay, private viewContainerRef: ViewContainerRef) {}

To show a modal overlay, you need either a Template or an Angular Component holding the content you would like to show. Let’s look at how you can use both below:

Using a Template

Inside the template of our component, let’s define a new template and add our overlay content:

<ng-template #tpl>
  <div class="modal-card">
  <header class="modal-card-head">
    …
  </header>
  <section class="modal-card-body">
    …
  </section>
  <footer class="modal-card-foot">
    …
  </footer>
 </div>
</ng-template>

Then, add a method to show the overlay and it accepts an ng-template reference as the parameter.

openWithTemplate(tpl: TemplateRef) {}

Then, Inside the above method, we are going to create an overlay. We will start by defining the configs of the overlay – OverlayConfig. In our case, we will just set the hasBackdrop and backdropClass properties. For backdropClass we are using modal-background a Bulma CSS Framework class. You can find all the Overlay Configurations you can add here.

const configs = new OverlayConfig({
 hasBackdrop: true,
 panelClass: ['modal', 'is-active'],
 backdropClass: 'modal-background'
});

NB: For backdrop click to dismiss the modal overlay to work, you might need to disable pointer-events for your modal, for some CSS Frameworks like Bulma. This is because CDK Overlay doesn’t add them to DOM in the nested order of modal ➡ modal-background ➡ modal-content, but rather modal ➡ modal-content, while the backdrop is a separate div tag not nested under modal, but on a level above modal class div tag.

For Bulma CSS framework case, you can override the default behavior like this:

.modal {
  pointer-events: none !important;
}

.modal-content {
  pointer-events: all !important;
}

Then, let’s create an OverlayRef, by using the create method of the Overlay service and pass the configs we just created above:

const overlayRef = this.overlay.create(configs);

And then we can attach our template, using TemplatePortal, passing our template and ViewContainerRef which we injected into our component:

overlayRef.attach(new TemplatePortal(tpl, this.viewContainerRef));

Now, we can trigger the method with a click of a button:

<button (click)="openWithTemplate(tpl)" >
 Show
</button>

Using a Component

The difference between the two is that we will be using ComponentPortal instead of TemplatePortal to attach the component to the OverlayRef.

this.overlayRef.attach(
 new ComponentPortal(OverlayComponent, this.viewContainerRef)
);

NB: The component must be added to the list of entryComponents in your App Module.

Closing Modal Overlay on Backdrop Clip

You can close the overlay when the backdrop is clicked by subscribing to the backdropClick() and then calling the dispose method.

overlayRef.backdropClick().subscribe(() => overlayRef.dispose());

Making a Re-usable Modal Overlay

Building modal overlays as shown above works very well if you are building one or two of them, however, it does not really scale very well. Wouldn’t it be nice if you could build a re-usable modal overlay that you can then use across your Angular project or projects? Wouldn’t it also be nice if we could be able to pass data to and receive data from the modal?

Objective

  • A service to open the modal, than can be injected into any component

  • A way to subscribe to when the modal is closed and access the response.

  • Pass data to the modal

  • Pass data as a String, Template or Component.

Overlay Ref Class

We are going to start by extending the OverlayRef. We will create a custom OverlayRef, creatively named MyOverlayRef, which is going to accept the OverlayRef, content and the data to pass to our modal overlay. The content can be of type string, TemplateRef or Component.

// R = Response Data Type, T = Data passed to Modal Type
export class MyOverlayRef<R = any, T = any> {
 …
 constructor(public overlay: OverlayRef, public content: string | TemplateRef<any> | Type<any>, public data: T ) {
  …
 }
 …
}

Then, Inside the MyOverlayRef class, we are going to add a BehaviorSubject property named afterClosed$ which we can subscribe to get data once the overlay is closed.

afterClosed$ = new Subject>();

The behavior subject is going to pass back an OverlayCloseEvent, which contains the data from modal and how the modal was closed. Feel free to modify this to cover your needs.

export interface OverlayCloseEvent {
 type: 'backdropClick' | 'close';
 data: R;
}

Next, we need to add a private method to close the overlay. The method will dispose off the overlay, pass the OverlayCloseEvent back to the subscriber and complete the afterClosed$ Observable.

private _close(type: 'backdropClick' | 'close', data: R) {
  this.overlay.dispose();
  this.afterClosed$.next({
   type,
   data
  });

  this.afterClosed$.complete();
 }

And then, we are going to add a second public close method. It will only accept data as a parameter and will call the private _close method, to close the modal.

close(data?: R) {
 this._close('close', data);
}

And finally, we are going to subscribe to backdropClick and close the modal when clicked. We are adding this subscriber to the MyOverlayRef constructor.

overlay.backdropClick().subscribe(() => this._close('backdropClick', null));

Overlay Component

Next, we are going to add a special component that we will use to show our modal content. If it is a simple string, we will bind it to a div, while we can use either ngTemplateOutlet and ngComponentOutlet to load the template and component respectively.

Component Class

We are going to start by injecting an instance of our MyOverlayRef into the component.

constructor(private ref: MyOverlayRef) {}

And then, let’s define 3 more properties inside our component class:

contentType: 'template' | 'string' | 'component' = 'component';
content: string | TemplateRef | Type;
context;

Then, OnInit, we need to determine the content type and set the above properties appropriately.

ngOnInit() {
  if (typeof this.content === 'string') {
   this.contentType = 'string';
  } else if (this.content instanceof TemplateRef) {
   this.contentType = 'template';
   this.context = {
    close: this.ref.close.bind(this.ref)
   };
  } else {
   this.contentType = 'component';
  }
}

And finally, we are going to be adding a global close button, so let’s add a close method:

close() {
 this.ref.close(null);
}

And finally, remember to add the Overlay component as an entryComponent in your app module.

Component Template

In the template, we are going to use ngSwitch to switch between content type and add a global close button for our modal.

<div class="modal-content">
 <ng-container [ngSwitch]="contentType">
  <ng-container *ngSwitchCase="'string'">
      <div class="box">
        <div [innerHTML]="content"></div>
   </div>
  </ng-container>
  
  <ng-container *ngSwitchCase="'template'">
   …
  </ng-container>

  <ng-container *ngSwitchCase="'component'">
   …
  </ng-container>
 </ng-container>
</div>

<!-- You can also add a global close button -->
<button (click)="close()" class="modal-close is-large" aria-label="close"></button>

For template content type, we will use ngTemplateOutlet, passing the template, which is the content and then pass the context:

<ng-container *ngTemplateOutlet="content; context: context"></ng-container>

And while for component content type, we will use ngComponentOutlet, passing the Component, which is the content:

<ng-container *ngComponentOutlet="content"></ng-container>

The Overlay Service

Next, we are going to create an Overlay service, which we can inject into any component we want to use our modal overlay. Where we are going to inject Overlay Service and the Injector.

export class OverlayService {
  constructor(private overlay: Overlay, private injector: Injector) {}
}

Then, add an open method, which will accept content and data. The data param, in this case, is the data you would like to pass to your modal.

open(
 content: string | TemplateRef | Type,data: T): MyOverlayRef {
 …
}

Inside the method, first, we need to create an OverlayRef object by using the Overlay create method. Feel free to customize the configs to suit your needs.

const configs = new OverlayConfig({
 hasBackdrop: true,
 panelClass: ['modal', 'is-active'],
 backdropClass: 'modal-background'
});

const overlayRef = this.overlay.create(configs);

Then, let’s instantiate our MyOverlayRef Class passing the OverlayRef object we created above, then content and the data, both from the method parameters.

const myOverlayRef = new MyOverlayRef(overlayRef, content, data);

Create an injector using PortalInjector, so that we can inject our custom MyOverlayRef object to the overlay component, we created above.

const injector = this.createInjector(myOverlayRef, this.injector);

And finally use ComponentPortal, to attach the OverlayComponent we created above and the newly created injector and return a MyOverlayRef object.

overlayRef.attach(new ComponentPortal(OverlayComponent, null, injector));
return myOverlayRef;

And here is the method for creating a custom injector using PortalInjector:

createInjector(ref: MyOverlayRef, inj: Injector) {
 const injectorTokens = new WeakMap([[MyOverlayRef, ref]]);
 return new PortalInjector(inj, injectorTokens);
}

And that’s it, we now have a re-usable modal overlay, that we can use anywhere inside our application.

Usage

First, inject the Overlay Service in the component where you would like to open a new modal overlay.

constructor(private overlayService: OverlayService) {}

Then, inside the method you would want to trigger the modal overlay, you just use the open method and pass the content and any data you want to pass to the modal overlay.

const ref = this.overlayService.open(content, null);

ref.afterClosed$.subscribe(res => {
 console.log(res);
});

The content can be a simple string or a Template or a Component.

String

const ref = this.overlayService.open("Hello World", null);

Template

<ng-template #tpl let-close="close">
  <div class="modal-card">
  <section class="modal-card-body">
   A yes no dialog, using template
  </section>
  <footer class="modal-card-foot">
   <div class="buttons">
    <button (click)="close('yes')" type="button" class="button is-success">Yes</button>
    <button (click)="close('no')" type="button" class="button is-danger">No</button>
   </div>
  </footer>
 </div>
</ng-template>

And a button to open the modal:

<button (click)="open(tpl)" class="button is-small is-primary">
 Show
</button>

And then open the overlay with an open method:

open(content: TemplateRef<any>) {
 const ref = this.overlayService.open(content, null);
 ref.afterClosed$.subscribe(res => {
  console.log(res);
 });
}

Component

open() {
 const ref = this.overlayService.open(YesNoDialogComponent, null);
 ref.afterClosed$.subscribe(res => {
  console.log(res);
 });
}

You can also inject the MyOverlayRef inside the component to access data and the close method.

constructor(private ref: MyOverlayRef) {}

This allows you to pass data to the component and trigger the closing of the modal from within the component.

close(value: string) {
 this.ref.close(value);
}

NB: Please remember to add the component as an entryComponent inside your App Module.

You can find all of the above code here and the demo here.

Thank you for reading !

Angular Tutorial - Learn Angular from Scratch

Angular Tutorial - Learn Angular from Scratch

Angular Tutorial - Learn Angular from Scratch: This course is for beginners who are curious on how to get started with Angular. In this course you will learn how to download, install and play around with Angular. We teach you the main components of Angular, so that you can get up and running with it asap. You will learn now to start building applications with Angular.

This course is for beginners who are curious on how to get started with Angular. In this course you will learn how to download, install and play around with Angular. We teach you the main components of Angular, so that you can get up and running with it asap. You will learn now to start building applications with Angular.

Learning Angular can be a daunting experience that's why this course was created; to give you an easier learning experience with it.

What am I going to get from this course?

  • You will learn the mayor fundamentals of Angular
  • You will learn how to get up and running with Angular
  • You will learn to create Applications using Angular 5 and beyond

What you'll learn

  • You will learn the mayor fundamentals of Angular
  • You will learn how to get up and running with Angular
  • You will learn to create Applications using Angular 5 and beyond

Angular 7 Tutorial - Learn Angular 7 by Example

Angular 7 Tutorial - Learn Angular 7 by Example

Watch or read this full crash course on learning Angular 7, tutorial is perfectly suited towards a beginner with no prior Angular experience.

Watch or read this full crash course on learning Angular 7, tutorial is perfectly suited towards a beginner with no prior Angular experience.

Ever since the release of Angular 2, I have created a full course for each new iteration. Today is no different, as Angular 7 just released!

With this beginner’s crash course, I make the assumption that you have never worked with Angular before. Therefore, this tutorial is perfectly suited towards a beginner with no prior Angular experience. The only thing you should be familiar with is HTML, CSS and JavaScript.

In this course, you’re going to discover just how powerful Angular 7 is when it comes to creating frontend web apps. Let’s get started!

If you prefer watching a video…

Be sure to Subscribe to the Official Coursetro Youtube Channel for more videos.

Installation

You’re first going to need to install the Angular CLI (Command Line Interface) tool, which helps you start new Angular 7 projects as well as assist you during development. In order to install the Angular CLI, you will need Nodejs. Make sure you install this with the default options and reload your command line or console after doing so.

In your command line, type:

> npm install -g @angular/cli

Once complete, you can now access the CLI by simply starting any commands with ng.

Hop into whichever folder you want to store your projects, and run the following command to install a new Angular 7 project:

> ng new ng7-pre

It’s going to present you with a couple questions before beginning:

? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? SCSS   [ http://sass-lang.com   ]

It will take a minute or two and once completed, you can now hop into the new project folder by typing:

> cd ng7

Open up this project in your preferred code editor (I use Visual Studio Code, and you can launch it automatically by typing code . in the current folder), and then run this command to run a development server using the Angular CLI:

> ng serve -o

-o is for open, this flag will open your default browser at http://localhost:4200. Tip: You can type ng to get a list of all available commands, and ng [command] --help to discover all their flags.

Awesome! If all went smooth, you should be presented with the standard landing page template for your new Angular 7 project:

Angular 7 Components

The most basic building block of your Angular 7 application (and this is a concept that’s not new) is the component. A component consists of three primary elements:

  • The HTML template
  • The logic
  • The styling (CSS, Sass, Stylus, etc…)

When we use the Angular CLI to start a new project, it generates a single component, which is found in /src/app/:

/app.component.html
/app.component.scss
/app.component.ts

While we have three files here that represent the three elements above, the .ts (TypeScript) is the heart of the component. Let’s take a look at that file:

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'ng7-pre';
}


Here, because this is a component, we’re importing Component from the @angular/core library, and then it defines what’s called a @Component decorator, which provides configuration options for that particular component.

As you can see, it’s referencing the location of the HTML template file and the CSS file with the templateUrl property and the styleUrls property.

The logic of the component resides in the class at the bottom. As you can see, the CLI starter template simply defines a single property called title.

Let’s use the Angular CLI to create our own components that we’ll need going forward. In the console, issue the following commands:

> ng generate component nav
// output

> ng g c about
// output

> ng g c contact
// output

> ng g c home
// output

Notice we first use the full syntax to generate a component, and then we use a shorthand syntax, which makes life a little bit easier. The commands do the same thing: generate components.

When we generate components this way, it will create a new folder in the /src/ folder based on the name we gave it, along with the respective template, CSS, .ts and .spec (for testing) files.

Angular 7 Templating

You may have noticed that one of the components we generated was called nav. Let’s implement a header bar with a navigation in our app!

The first step is to visit the app.component.html file and specify the following contents:

<app-nav></app-nav>

<section>
  <router-outlet></router-outlet>
</section>

So, we’ve removed a bunch of templating and placed in , what does this do and where does it come from?

Well, if you visit /src/app/nav/nav.component.ts you will see that in the component decorator, there’s a selector property bound to the value of app-nav. When you reference the selector of a given component in the form of a custom HTML element, it will nest that component inside of the component it’s that’s referencing it.

If you save the file you just updated, you will see in the browser we have a simple, nav works! And that’s because the nav.component.html file consists of a simple paragraph stating as much.

At this point, let’s specify the following HTML to create a simple navigation:

<header>
  <div class="container">
    <a routerLink="/" class="logo">apptitle</a>
    <nav>
      <ul>
        <li><a routerLink="/">Home</a></li>
        <li><a routerLink="/about">About</a></li>
        <li><a routerLink="/contact">Contact us</a></li>
      </ul>
    </nav>
  </div>
</header>

The only thing that might look a little strange is routerLink. This is an Angular 7 specific attribute that allows you to direct the browser to different routed components. The standard href element will not work.

While we’re here on the subject of templating, what if we wanted to display properties that are coming from our component? We use what’s called interpolation.

Make the following adjustment to our template:

<!-- From: -->
<a routerLink="/">myapp</a>

<!-- To: -->
<a routerLink="/">{{ appTitle }}</a>


Interpolation is executed by wrapping the name of a property that’s defined in the component between {{ }}.

Let’s define that property in nav.component.ts:

export class NavComponent implements OnInit {

  appTitle: string = 'myapp';
  // OR (either will work)
  appTitle = 'myapp';

  constructor() { }

  ngOnInit() {
  }

}

You can use the TypeScript way of defining properties or standard JavaScript. Save the file and you will see myapp is back in the template.

There’s a lot more to templating, but we will touch on those topics as we continue. For now, let’s apply style to our header.

First, let’s visit the global stylesheet by opening /src/styles.scss and define the following rulesets:

@import url('https://fonts.googleapis.com/css?family=Montserrat:400,700');

body, html {
    height: 100%;
    margin: 0 auto;
}

body {
    font-family: 'Montserrat';
    font-size: 18px;
}

a {
    text-decoration: none;
}

.container {
    width: 80%;
    margin: 0 auto;
    padding: 1.3em;
    display: grid;
    grid-template-columns: 30% auto;

    a {
        color: white;
    }
}

section {
    width: 80%;
    margin: 0 auto;
    padding: 2em;
}

Visit nav/component.scss and paste the following contents:

header {
    background: #7700FF;

    .logo {
        font-weight: bold;
    }

    nav {
        justify-self: right;

        ul {
            list-style-type: none;
            margin: 0; padding: 0;

            li {
                float: left;

                a {
                    padding: 1.5em;
                    text-transform: uppercase;
                    font-size: .8em;

                    &:hover {
                        background: #8E2BFF;
                    }
                }
            }
        }
    }
}

If you save and refresh, this should be the result in the browser:

Awesome!

Angular 7 Routing

Now that we have a navigation, let’s make our little app actually navigation between our components as needed.

Open up /src/app/app-routing.module.ts and specify the following contents:

// Other imports removed for brevity

import { HomeComponent } from './home/home.component';
import { AboutComponent } from './about/about.component';
import { ContactComponent } from './contact/contact.component';

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'about', component: AboutComponent },
  { path: 'contact', component: ContactComponent },
];

// Other code removed for brevity

As we can see here, we’re defining importing our components and defining an object for each route inside of the routes constant. These route objects also accept other properties, which allow you to define URL parameters, but because our app is simple, we won’t be doing any of that.

Save this file and try clicking on the links above. You will see that each of the respective component’s HTML templating shows up in the  defined in app.component.html.

This is what the result should look like in the browser at this point:

You now know enough about Angular 7 to create a very simple website with routing! But let’s learn more than that.

Angular 7 Event Binding

In the next several sections, we’re going to use our /src/app/home component as a playground of sorts to learn features specific to Angular 7.

One of the most used forms of event binding is the click event. You often need to make your app respond when a user clicks something, so let’s do that!

Visit the /src/app/home/home.component.html template file and specify the following:

<h1>Home</h1>

<button (click)="firstClick()">Click me</button>

You define an event binding by wrapping the event between (), and calling a method. You define the method in the home.component.ts file as such:

export class HomeComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

  firstClick() {
    console.log('clicked');
  }

}

Save it, get out the browser console (CTRL+SHIFT+i) and click on the button. The output should show clicked. Great!

You can experiment with the other event types by replacing (click) with the names below:

(focus)="myMethod()"
(blur)="myMethod()" 
(submit)="myMethod()"  
(scroll)="myMethod()"

(cut)="myMethod()"
(copy)="myMethod()"
(paste)="myMethod()"

(keydown)="myMethod()"
(keypress)="myMethod()"
(keyup)="myMethod()"

(mouseenter)="myMethod()"
(mousedown)="myMethod()"
(mouseup)="myMethod()"

(click)="myMethod()"
(dblclick)="myMethod()"

(drag)="myMethod()"
(dragover)="myMethod()"
(drop)="myMethod()"

Angular 7 Class & Style Binding

Sometimes you may need to change the appearance of your UI from your component logic. There are two ways to do this, through class and style binding.

There are a lot of different methods you can use to control class binding, so we won’t cover them all. But I will cover some of the most common use cases.

Let’s say that you want to control whether or not a CSS class is applied to a given element. Update the h1 element in home.component.html to the following:

<h1 [class.gray]="h1Style">Home</h1>

Here, we’re saying that the CSS class of .gray should only be attached to the h1 element if the property h1Style results to true. Let’s define that in the home.component.ts file:

  h1Style: boolean = false;

  constructor() { }

  ngOnInit() {
  }

  firstClick() {
    this.h1Style = true;
  }

Let’s also define the .gray class in this component’s scss file:

.gray {
    color: gray;
}

Save it, and you can now click on the click me button to change the color of the Home title.

What if you wanted to control multiple classes on a given element? You can use ngClass. Modify the home component’s template file to the following:

<h1 [ngClass]="{
  'gray': h1Style,
  'large': !h1Style
}">Home</h1>

Then, add the large ruleset to the .scss file:

.large {
    font-size: 4em;
}

Now give it a shot in the browser. Home will appear large, but shrink down to the regular size when you click the button. Great!

You can also control appearance by changing the styles directly from within the template. Modify the template as such:

<h1 [style.color]="h1Style ? 'gray': 'black'">Home</h1>

Refresh and give this a shot by clicking the button.

Like ngClass() there’s also an ngStyle() that works the same way:

<h1 [ngStyle]="{
  'color': h1Style ? 'gray' : 'black',
  'font-size': !h1Style ? '1em' : '4em'
}">Home</h1>

Give this a go! Awesome!

Angular 7 Services

Services in Angular 7 allow you to define code that’s accessible and reusable throughout multiple components. A common use case for services is when you need to communicate with a backend of some sort to send and receive data.

> ng generate service data

Open up the new service file /src/app/data.service.ts and let’s create the following method:

// Other code removed for brevity

export class DataService {

  constructor() { }

  firstClick() {
    return console.log('clicked');
  }
}

To use this in a component, visit /src/app/home/home.component.ts and update the code to the following:

import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {

  constructor(private data: DataService) { }

  ngOnInit() {
  }

  firstClick() {
    this.data.firstClick();
  }

}


There are 3 things happening here:

  • The HTML template
  • The logic
  • The styling (CSS, Sass, Stylus, etc…)

If you try this, you will see that it works as clicked will be printed to the console. Awesome! This means that you now know how to create methods that are accessible from any component in your Angular 7 app.

Angular 7 HTTP Client

Angular comes with its own HTTP library that we will use to communicate with a fake API to grab some data and display it on our home template. This will take place within the data.service file that we generated with the CLI.

In order to gain access to the HTTP client library, we have to visit the /src/app/app.module.ts file and make a couple changes. Up until this point, we haven’t touched this file, but the CLI has been modifying it based on the generate commands we’ve issued to it.

Add the following to the imports section at the top:

// Other imports
import { HttpClientModule } from '@angular/common/http';

Next, add it to the imports array:

  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,    // <-- Right here
  ],

Now we can use it in our /src/app/data.service.ts file:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';  // Import it up here

@Injectable({
  providedIn: 'root'
})
export class DataService {

  constructor(private http: HttpClient) { }

  getUsers() {
    return this.http.get('https://reqres.in/api/users')
  }
}


reqres.in is a free public API that we can use to grab data.

Open up our home.component.ts file and modify the following:

export class HomeComponent implements OnInit {

  users: Object;

  constructor(private data: DataService) { }

  ngOnInit() {
    this.data.getUsers().subscribe(data => {
        this.users = data
        console.log(this.users);
      }
    );
  }

}

The first thing you might notice is that we’re placing the code inside of the ngOnInit() function, which is a lifecycle hook for Angular. Any code placed in here will run when the component is loaded.

We’re defining a users property, and then we’re calling the .getUsers() method and subscribing to it. Once the data is received, we’re binding it to our users object and also console.logging it.

Give it a try in the browser and you will see the console shows an object that’s returned. Let’s display it on our home template!

Open up home.component.html and specify the following:

<h1>Users</h1>

<ul *ngIf="users">
  <li *ngFor="let user of users.data">
    <img [src]="user.avatar">
    <p>{{ user.first_name }} {{ user.last_name }}</p>
  </li>
</ul>

Great! Let’s specify some CSS to make this look better in home.component.scss:

ul {
    list-style-type: none;
    margin: 0;padding: 0;

    li {
        background: rgb(238, 238, 238);
        padding: 2em;
        border-radius: 4px;
        margin-bottom: 7px;
        display: grid;
        grid-template-columns: 60px auto;

        p {
            font-weight: bold;
            margin-left: 20px;
        }

        img {
            border-radius: 50%;
            width: 100%;
        }
    }
}

View the result in the browser:

Awesome!

Angular 7 Forms

If you recall, we generated a component called contact. Let’s create a contact form so that you can learn how to use forms in Angular 7.

Angular 7 provides you with two different approaches to dealing with forms: template driven and reactive forms. I’m not going to go into the differences between these two approaches, but reactive forms generally provide you with more control andform validation can be unit tested as opposed to template driven forms.

To get started, we have to visit the app.module.ts file and import the Reactive Forms Module:

// other imports
import { ReactiveFormsModule } from '@angular/forms';

// other code
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    ReactiveFormsModule  // <- Add here
  ],

Next, visit the contact.component.ts file and specify the following

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-contact',
  templateUrl: './contact.component.html',
  styleUrls: ['./contact.component.scss']
})
export class ContactComponent implements OnInit {

  messageForm: FormGroup;
  submitted = false;
  success = false;

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit() {
    this.messageForm = this.formBuilder.group({
      name: ['', Validators.required],
      message: ['', Validators.required]
    });
  }

  onSubmit() {
    this.submitted = true;

    if (this.messageForm.invalid) {
        return;
    }

    this.success = true;
}

}


First, we’re importing FormBuilder, FormGroup, Validators from @angular/forms.

Then we’re setting a few boolean properties that will help us determine when the form has been submitted and if it validation is successful.

Then we’re creating an instance of the formBuilder in the constructor. We then use this form building to construct our form properties in the ngOnInit() lifecycle hook.

We have two properties, name and message.

Then we created an onSubmit() method that will be called when the user submits the form. This is typically where you would call upon a method in the service to communicate with a mail service of sorts.

Next, visit contact.component.html:

<h1>Contact us</h1>

<form [formGroup]="messageForm" (ngSubmit)="onSubmit()">

    <h5 *ngIf="success">Your form is valid!</h5>

    <label>
      Name:
      <input type="text" formControlName="name">
      <div *ngIf="submitted && messageForm.controls.name.errors" class="error">
        <div *ngIf="messageForm.controls.name.errors.required">Your name is required</div>
      </div>
    </label>

    <label>
      Message:
      <textarea formControlName="message"></textarea>
      <div *ngIf="submitted && messageForm.controls.message.errors" class="error">
        <div *ngIf="messageForm.controls.message.errors.required">A message is required</div>
      </div>
    </label>

    <input type="submit" value="Send message" class="cta">

  </form>

  <div *ngIf="submitted" class="results">
    <strong>Name:</strong> 
    <span>{{ messageForm.controls.name.value }}</span>

    <strong>Message:</strong> 
    <span>{{ messageForm.controls.message.value }}</span>
  </div>


Baked in here is a full form with validation. It also prints out the form values beneath it when the form has been submitted.

Let’s update the css for the component to make it look decent:

label {
    display: block;

    input, textarea {
        display: block;
        width: 50%;
        margin-bottom: 20px;
        padding: 1em;
    }

    .error {
        margin-top: -20px;
        background: yellow;
        padding: .5em;
        display: inline-block;
        font-size: .9em;
        margin-bottom: 20px;
    }
}

.cta {
    background: #7700FF;
    border: none;
    color: white;

    text-transform: uppercase;
    border-radius: 4px;
    padding: 1em;
    cursor: pointer;
    font-family: 'Montserrat';
}

.results {
    margin-top: 50px;

    strong {
        display: block;
    }
    span {
        margin-bottom: 20px;
        display: block;
    }
}

Save it, and the result in the browser should look like this!

Awesome!

Conclusion

As you can see, Angular 7 is quite powerful but we’ve only just scratched the surface. If you’re a beginner, I recommend trying to create a really simple project using what you’ve learned so far and then take it from there.

Learn More

Angular 7 (formerly Angular 2) - The Complete Guide

Learn and Understand AngularJS

Angular Crash Course for Busy Developers

The Complete Angular Course: Beginner to Advanced

Angular (Angular 2+) & NodeJS - The MEAN Stack Guide

Become a JavaScript developer - Learn (React, Node,Angular)

Angular (Full App) with Angular Material, Angularfire & NgRx

The Web Developer Bootcamp

Angular 9 Service Tutorial: Creating API and HttpClient

Angular 9 Service Tutorial: Creating API and HttpClient

In this Angular 9 Service tutorial shows you the Angular Service example, we will create an API with HttpClient service. How to create a Service class and write the APIs in it. We also learned how to access the Service methods and properties in Angular components. Angular Service contains the various methods and functions to manage the data arriving from the server.

In this tutorial, we are going to discuss Angular 8/9 Service. To show you the Angular Service example, we will create API with HttpClient service.

Angular Service contains the various methods and functions to manage the data arriving from the server.

Why Angular Service Class?

  • To handle the features that are separate from components such as authentication, CRUD operations.
  • To share the data among various components in an Angular app.
  • To make the Testing and Debugging simple.
  • To write the re-usable code to centrally organise the application.

Table of Contents

  • What is Angular Service?
  • Set Up Angular CLI
  • Setting Up Angular Project
  • Creating Service Class
  • Creating Methods in Service Class
  • Access Service Methods in Components
  • Conclusion
What is Angular Service?

Most of the time, we get into the situation where we need to use the same code again and again. Using repetitive code in multiple components becomes a headache.

When the size of an Angular application gets bigger, then It almost becomes difficult to manage the code base of our app. In this scenario, the best practice will be to write the reusable code.

To deal with this kind of situation, we can undoubtedly take the help of the Services class in Angular. Its a JavaScript class and includes properties and methods to share the data between unknown components classes.

Set Up Angular CLI

To install the Angular project, you need to have latest version of Angular CLI installed.

npm install -g @angular/[email protected]

In case of error prefix sudo with the above command and provide admin password.

Setting Up Angular Project

Run the below command to install the brand new Angular project.

ng new angular-service-example

Run command to get inside the project folder.

cd angular-service-example

Start the application in the browser.

ng serve --open
Creating Service Class

Our service will contain the create, read, update and delete methods for a demo task management app. To create an Angular Service class, you need to run the following command via Angular CLI.

ng generate service crud

Above command creates the following files in the src/app folder.

# src/app/crud.service.spec.ts

# src/app/crud.service.ts

Here, is the file crud.service.ts file we generated for Angular Service example.

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

@Injectable({
  providedIn: 'root'
})

export class CrudService {

  constructor() { }

}

@Injectable(): Decorator that marks a class as available to be provided and injected as a dependency.

providedIn: Injectors make the communication with injectable that is something based on with @NgModule or other InjectorType, even by specifying that this injectable should be provided in the ‘root’ injector.

Next, we need to import the Service Class in the app.module.ts, and also register the service class in the providers array.

// Service class
import { CrudService } from './crud.service';

@NgModule({
  declarations: [...],
  imports: [...],
  providers: [CrudService],
  bootstrap: [...]
})

Importing and registering the service class in Angular’s main app module means that, service class is available throughout the application.

Creating Methods in Service Class

In this part of the tutorial, we will write API in Angular Service Class. In the below example we wrote the CRUD operations using the HttpClient service.

To make these methods work you also need to import and register HttpClientModule in the main app module file.

import { HttpClientModule } from '@angular/common/http';

@NgModule({
  imports: [
    HttpClientModule
   ]
})

In the API section you need to pass the API URL in order to make this API work.

import { Injectable } from '@angular/core';
import { Observable, throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { HttpClient, HttpHeaders, HttpErrorResponse } from '@angular/common/http';

@Injectable({
  providedIn: 'root'
})

export class CrudService {

  apiUrl: string = 'enter-your-api-url';
  headers = new HttpHeaders().set('Content-Type', 'application/json');

  constructor(private http: HttpClient) { }

  // Create
  createTask(data): Observable<any> {
    let API_URL = `${this.apiUrl}/create-task`;
    return this.http.post(API_URL, data)
      .pipe(
        catchError(this.error)
      )
  }

  // Read
  showTasks() {
    return this.http.get(`${this.apiUrl}`);
  }

  // Update
  updateTask(id, data): Observable<any> {
    let API_URL = `${this.apiUrl}/update-task/${id}`;
    return this.http.put(API_URL, data, { headers: this.headers }).pipe(
      catchError(this.error)
    )
  }

  // Delete
  deleteTask(id): Observable<any> {
    var API_URL = `${this.apiUrl}/delete-task/${id}`;
    return this.http.delete(API_URL).pipe(
      catchError(this.error)
    )
  }

  // Handle Errors 
  error(error: HttpErrorResponse) {
    let errorMessage = '';
    if (error.error instanceof ErrorEvent) {
      errorMessage = error.error.message;
    } else {
      errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
    }
    console.log(errorMessage);
    return throwError(errorMessage);
  }

}
Access Service Methods in Components

To access the Service methods, we need to import the Service in the component file, let’s import the CrudService class in the app.component.ts.

import { CrudService } from './crud.service';

Next, we need to follow the dependency injection pattern and inject the Service class inside the constructor.

export class AppComponent {

  constructor(private crudService: CrudService){}

}

Next, we can easily access all the CrudService methods, and we are using the ngOnInit() lifecycle hook to access the showTask() method of Angular Service class.

import { Component, OnInit } from '@angular/core';
import { CrudService } from './crud.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit {

  constructor(private crudService: CrudService) { }

  ngOnInit() {
    console.log(this.crudService.showTasks);
  }

}

Conclusion

Now, Angular 8/9 Service Tutorial is completed with examples. In this tutorial, we looked at how to create a Service class and write the APIs in it. We also learned how to access the Service methods and properties in Angular components. I hope you liked this tutorial. Please share this tutorial with others.