Chapter 5: Angular Declarables, Bootstrapping, and Modularity
Activity 13: Communicating Between Two Components Using Observable
Create the app-header component using the CLI, as shown here:
ng generate component app-header
Create the app-content component using the following CLI command:
ng generate component app-content
Create the user model and interface in user.model.ts using the following command:
export interface User { firstName: string; lastName: string; }
Create the user service and update the server:
ng generate server user import { Injectable } from '@angular/core'; import { BehaviorSubject } from 'rxjs'; @Injectable() export class UserService { private user = new BehaviorSubject<boolean>(false); //create user as behavior cast = this.user.asObservable(); //cast user as observable constructor() { } User(newUser) { this.user.next(newUser); } }
Define the user and inject service into the app-header.component.ts class using the following code:
import { Component, OnInit } from '@angular/core'; import { User } from '../user/user.model'; import { UserService } from '../user.service'; @Component({ selector: 'app-header', templateUrl: './app-header.component.html', styleUrls: ['./app-header.component.scss'] }) export class AppHeaderComponent implements OnInit { user: User = { firstName: 'Paul', lastName: 'Oluyege' }; isLoggedIn: boolean; constructor(private usersService:UserService) { }
Define the user and inject service into the app-content.component.ts class using the following code:
import { Component, OnInit } from '@angular/core'; import { User } from './../user/user.model'; import { UserService } from '../user.service'; @Component({ selector: 'app-content', templateUrl: './app-content.component.html', styleUrls: ['./app-content.component.scss'] }) export class AppContentComponent implements OnInit { user: User = { firstName: 'Paul', lastName: 'Oluyege' }; isLoggedIn: boolean; constructor(private usersService: UserService) { }
Write ngOnInit(), login(), signup(), and logout() methods for the app-header.component.ts class, as shown here:
ngOnInit() { this.usersService.cast.subscribe(user=> this.isLoggedIn = user); } login() { this.isLoggedIn = true; this.usersService.User(this.isLoggedIn); } signup() { this.isLoggedIn = true; this.usersService.User(this.isLoggedIn); } logout() { this.isLoggedIn = false; this.usersService.User(this.isLoggedIn); } }
Write ngOnInit(), login(), signup(), and logout() methods for the app-content.component.ts class, as shown here:
ngOnInit() { this.usersService.cast.subscribe(user => this.isLoggedIn = user); this.isLoggedIn = false; } login() { this.isLoggedIn = true; this.usersService.User(this.isLoggedIn); } logout() { this.isLoggedIn = false; this.usersService.User(this.isLoggedIn); } }
Update the app-header.component.html template using the following code:
<div class="app-header"> <div class="title" routerLink="/">Packt MEANStack Courseware</div> <div class="profile-dropdown" *ngIf="isLoggedIn"> <div class="initials"> {{user.firstName.charAt(0)}}{{user.lastName.charAt(0)}} </div> </div> <div class="action-btns" *ngIf="!isLoggedIn"> <button class="app-btn login-btn" (click)="login()">Login</button> <button class="app-btn signup-btn" (click)="signup()">Signup</button> </div> <div class="action-btns" *ngIf="isLoggedIn"> <button class="app-btn logout-btn" (click)="logout()">Logout</button> </div> </div>
Update the app-content.component.html template using the following code:
<div class="app-content"> <div class="user-profile" *ngIf="isLoggedIn"> Hi {{user.firstName}} {{user.lastName}}! Welcome to MEANStack class </div> <div class="action-btn"> <button class="app-btn" *ngIf="!isLoggedIn" (click)="login()">Login</button> <button class="app-btn" *ngIf="isLoggedIn" (click)="logout()">Logout</button> </div> </div>
Update styles for both components (app-header and app-content), as shown here:
// app-content-component.scss .app-content { padding: 40px; .user-profile { margin-bottom: 20px; } } // app-header-component.scss .app-header { background: #e94e06; height: 44px; color: white; padding: 6px 10px; display: flex; flex-direction: row; align-items: center; box-shadow: 0 3px 5px -1px rgba(0,0,0,.2), 0 6px 10px 0 rgba(0,0,0,.14), 0 1px 18px 0 rgba(0,0,0,.12); .logo { //[…] } } } }
Update the app.component.html template with the following code:
<app-header></app-header> <app-content></app-content>
Run ng serve on the CLI and open the browser on localhost:4200 to see the output and test it, as shown in the following screenshot:
Activity 14: Creating a Lazy Loaded Application
Create an Angular project with the name users, as shown here:
ng new users --routing
Note that the --routing flag generates a file called app-routing.module.ts, which is one of the files you need for setting up lazy loading for your feature module.
Create a users-list feature module with routing:
ng generate module users-list --routing
Add a user-list component to the feature module using the following code:
ng generate component users-list / users-list
Create a users-details feature module with routing using the following code:
ng generate module users-details --routing
Add a user-detail component to the feature module using the following code:
ng generate component users-detail / users-detail
Globally install the json-server on your system using npm or yam:
npm install -g json-server
Create a new JSON file named db.json and fill it with data from https://api.myjson.com/bins/10v4ns. Then, launch this file on the json-server using the following code:
json-server --watch db.json
Add a user-list service using the following code:
ng generate service service/users-list
Update the routes array in AppRoutingModule with the following code:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: 'userslist', loadChildren: './users-list/users-list.module#UsersListModule' }, { path: 'userslist/:id', loadChildren: './users-detail/users-detail.module#UsersDetailModule' }, { path: '', redirectTo: '', pathMatch: 'full' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
Configure the feature module's routes in users-list-routing.module.ts by first importing the component at the top of the file with the other JavaScript import statements and then add the route to UserListComponent:
Here is the code for importing the component:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { UsersListComponent} from './users-list.component' const routes: Routes = [ { path: "", component: UsersListComponent}, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class UsersListRoutingModule { }
Configure the feature modules for users-detail-routing.module.ts using the following code:
import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { UsersDetailComponent} from './users-detail.component' const routes: Routes = [ { path: "", component: UsersDetailComponent}, ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule] }) export class UsersDetailRoutingModule { }
Create the user model and update it with the following code:
ng generate cl model/user export class Users { first: string; second: string; id: number; phone:string; picture:string; email:string; }
Write the service functions, as shown here:
import { Injectable } from '@angular/core'; import { Users } from "../model/users.model"; import {HttpClient} from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class UsersListService { dataurl = "http://localhost:3000/results"; constructor(private http: HttpClient) { } public getUsers(): Observable<Users[]> { return this.http.get<Users[]>(this.dataurl); } public getUser(id: string): Observable<Users> { return this.http.get<Users>('${this.dataurl}?id=${id}'); } }
Update and inject the service into users-list.component.ts using the following code:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { Router } from '@angular/router'; import { Users } from "../model/users.model"; import { UsersListService } from "../service/users-list.service"; @Component({ selector: 'app-users-list', templateUrl: './users-list.component.html', styleUrls: ['./users-list.component.css'] }) export class UsersListComponent implements OnInit { userlists: Users[]; constructor(private router: Router, private usersService: UsersListService) { } ngOnInit() { this.usersService.getUsers().subscribe((user: any) => { this.userlists = user; console.log(this.userlists); }); } }
Update and inject service into users-details.component.ts, as shown here:
import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from "@angular/router"; import { Router } from '@angular/router'; import { Users } from "../model/users.model"; import { UsersListService } from "../service/users-list.service"; @Component({ selector: 'app-users-detail', templateUrl: './users-detail.component.html', styleUrls: ['./users-detail.component.css'] }) export class UsersDetailComponent implements OnInit { user: Users; constructor(private router: Router, private route: ActivatedRoute, private usersService: UsersListService) { } ngOnInit(): void { this.usersService.getUser(this.route.snapshot.params["id"]).subscribe((user: any) => { this.user = user; }); }
Style the user-list component using the following code:
.selected { background-color: #CFD8DC !important; color: white; } //[…] .list-type1 ol.selected:hover { background-color: #BBD8DC !important; color: white; }
Style the users-details components using the following code:
@import url(https://fonts.googleapis.com/css?family=Raleway|Varela+Round|Coda); @import url(http://weloveiconfonts.com/api/?family=entypo); [class*="entypo-"]:before { font-family: 'entypo', sans-serif; } //[…] .previous { background-color: #f1f1f1; color: black; }
Update the app.component.html template, as shown here:
<router-outlet></router-outlet>
Go to localhost:4200 and then test for /userslist and /userslist/1, as follows:
Type localhost/4200/userslist on the browser address bar and observe the number of resources requested, as shown here:
Type localhost/4200/userslist/1 on the browser address bar and observe the number of resources requested, as shown here: