1b - Brief Introduction To Angular

In this section we will use angular services and review observables with RxJS

1. Add a user service

ng g service services/user/user

2. Add HttpClientModule to AppModule

src/app/app.module.ts
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HomeComponent } from './home/home.component';
import { HttpClientModule } from '@angular/common/http'; // Added

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule     // Added
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

3. Make a User service

Add some fake data in a user.json file in the assets folder of your new app. This is in place of a URL to hit a real API, for no.

src/assets/users.json
[{ "name": "duncan" }, { "name": "sarah" }, { "name": "peter" }]

Make the service and inject in the HttpClient

src/app/services/user/user.service.ts
import { Injectable } from "@angular/core";
import { HttpClient } from "@angular/common/http";

@Injectable({
  providedIn: 'root'
})
export class UserService {
  apiUrl = './../../../assets/users.json';

  constructor(private httpClient: HttpClient) {}

  getUsers(): Observable<any> { {
    return this.httpClient.get(this.apiUrl);
  }
}

4. Add a UserList component and inject in the User service

Make a user-list component, 'c' is short hand for component.

ng g c user-list

Add a new eagerly loaded route for the UserList component

src/app/app-routing.module.ts
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { UserListComponent } from './user-list/user-list.component'; //added

const routes: Routes = [
  { path: '', component: HomeComponent },
  { path: 'user-list', component: UserListComponent }, //added
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Check the route works by navigating to http://localhost:4200/user-list

Inject user service and call its getUsers method and bind in to a local variable

src/app/user-list/user-list.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user/user.service';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {
  users$: any;
  constructor(private userService: UserService) {}

  ngOnInit() {
    this.users$ = this.userService.getUsers();
  }
}
src/app/user-list/user-list.component.ts
import { Component, OnInit, OnDestroy } from '@angular/core';
import { UserService } from '../services/user/user.service';
import { takeWhile } from 'rxjs/operators';
import { User } from '../models/user';

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit, OnDestroy {
  users: User[];
  componentActive = true;

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.userService
      .getUsers()
      .pipe(takeWhile(() => this.componentActive))
      .subscribe((users: User[]) => (this.users = users));
  }

  ngOnDestroy(): void {
    this.componentActive = false;
  }
}

Use the async pipe to and an ngFor template directive to subscribe and iterate over the users.

5. Use Angular ngFor to bind users

src/app/user-list/user-list.component.html
<p>
  user-list works!
</p>
<div *ngFor="let user of (users$ | async)"> {{user.name}}</div>

6. Add strong typing

Add User type to a models folder

ng g interface models/user
models/user.ts
export interface User {
  name: string;
}

Add User type to the service

src/app/services/user/user.service.ts
export class UserService {
  apiUrl = './../../../assets/users.json';            //changed

  constructor(private httpClient: HttpClient) {}

  getUsers(): Observable<User[]> {                    //changed
    return this.httpClient.get<User[]>(this.apiUrl);  //changed
  }
}

Add User type to the UserList component

src/app/user-list/user-list.component.ts
import { Component, OnInit } from '@angular/core';
import { UserService } from '../services/user/user.service';
import { Observable } from 'rxjs';     //changed
import { User } from '../models/user'; //changed

@Component({
  selector: 'app-user-list',
  templateUrl: './user-list.component.html',
  styleUrls: ['./user-list.component.css']
})
export class UserListComponent implements OnInit {
  users$: Observable<User[]>;                      //changed

  constructor(private userService: UserService) {}

  ngOnInit() {
    this.users$ = this.userService.getUsers();
  }
}

Extra reading

Naming observables - https://medium.com/@benlesh/observables-are-just-functions-but-also-collections-how-do-i-name-them-918c5ce2f64

Last updated