Pertama, pada sidenav, kita perlu tambahkan routerlink. Buka file sidenav.component.html, lalu ubah link href.
<mat-drawer-container class="app-sidenav-container" autosize>
<mat-drawer #drawer class="app-sidenav mat-elevation-z10" [mode]="isScreenSmall ? 'over' : 'side' " [opened]="!isScreenSmall">
<mat-toolbar color="primary">
<span>Contact</span>
</mat-toolbar>
<mat-nav-list>
<mat-list-item *ngFor="let user of users | async">
<!-- tambahkan router link pada element a -->
<a matLine [routerLink]="['/contactmanager', user.id]">
<mat-icon svgIcon="{{ user.avatar }}"></mat-icon> {{ user.name }}
</a>
</mat-list-item>
</mat-nav-list>
</mat-drawer>
<div class="app-sidenav-content">
<app-toolbar (toggleSidenav)="drawer.toggle()"></app-toolbar>
<div class="wrapper">
<router-outlet></router-outlet>
</div>
</div>
</mat-drawer-container>
Buka file contactmanager.module.ts, registrasikan route diatas.
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FlexLayoutModule } from '@angular/flex-layout';
import { FormsModule } from '@angular/forms';
import { Routes, RouterModule } from '@angular/router';
import { MaterialModule } from '../shared/material.module';
import { ContactmanagerAppComponent } from './contactmanager-app.component';
import { ToolbarComponent } from './components/toolbar/toolbar.component';
import { MainContentComponent } from './components/main-content/main-content.component';
import { SidenavComponent } from './components/sidenav/sidenav.component';
import { UserService } from './services/user.service';
import { HttpClientModule } from '@angular/common/http';
const routes : Routes = [
{
path: '', component: ContactmanagerAppComponent,
children: [
{path: ':id', component: MainContentComponent},
{path: '', component: MainContentComponent}
]
},
{path: '**', redirectTo: ''}
]
@NgModule({
declarations: [
ContactmanagerAppComponent,
ToolbarComponent,
MainContentComponent,
SidenavComponent,
],
imports: [
CommonModule,
HttpClientModule,
FormsModule,
MaterialModule,
FlexLayoutModule,
RouterModule.forChild(routes)
],
providers:[
UserService
]
})
export class ContactmanagerModule { }
Kemudian buka file main-content.component.ts, kita handle routing diatas.
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { User } from '../../models/user';
import { UserService } from '../../services/user.service';
@Component({
selector: 'app-main-content',
templateUrl: './main-content.component.html',
styleUrls: ['./main-content.component.scss']
})
export class MainContentComponent implements OnInit {
user! : User | undefined;
constructor(private route: ActivatedRoute, private userSrv: UserService) { }
ngOnInit(): void {
this.route.params.subscribe(params=>{
const id = params['id'];
this.userSrv.users.subscribe(users=>{
if(users.length==0) return;
this.user = this.userSrv.loadUserById(id);
});
});
}
}
Kemudian buka file user.service.ts, implementasikan method untuk loadUserById.
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { User } from '../models/user';
@Injectable({
providedIn: 'root'
})
export class UserService {
private _users : BehaviorSubject<User[]>;
private dataStore : {
users : User[]
}
constructor(private http: HttpClient) {
this.dataStore = {users :[]};
this._users = new BehaviorSubject<User[]>([]);
}
get users(): Observable<User[]>{
return this._users.asObservable();
}
loadAllUser(){
const url = 'https://spangularmaterial-default-rtdb.firebaseio.com/users.json';
return this.http.get<User[]>(url).subscribe(data =>{
this.dataStore.users = data;
this._users.next(Object.assign({}, this.dataStore).users);
}, error => {
console.log('error load user');
});
}
loadUserById(id:number){
return this.dataStore.users.find(x=> x.id == id);
}
}
Kemudian kita buka main-content.component.html, tambahkan code untuk menampilkan data user.
Link dokumentasi component yang digunakan:
<div *ngIf="!user">
<mat-spinner></mat-spinner>
</div>
<div *ngIf="user">
<mat-card>
<mat-card-header>
<mat-icon mat-card-avatar svgIcon="{{user.avatar}}"></mat-icon>
<mat-card-title>{{ user.name }}</mat-card-title>
<mat-card-subtitle>Birthday {{ user.birthDate | date:'d LLLL' }}</mat-card-subtitle>
</mat-card-header>
<mat-card-content>
<p>{{ user.bio }}</p>
</mat-card-content>
</mat-card>
</div>
Kemudian kita buka sidenav.component.ts, lakukan modifikasi untuk menampilkan data user index pertama, jika tersedia datanya.
Kita juga perlu menambahkan code untuk menutup sidenav setelah diclick (pada small screen).
import { BreakpointObserver, BreakpointState } from '@angular/cdk/layout';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Observable } from 'rxjs';
import { UserService } from '../../services/user.service';
import { User } from '../../models/user';
import { Router } from '@angular/router';
import { MatDrawer, MatSidenav } from '@angular/material/sidenav';
const SMALL_WIDTH_BP = 720;
@Component({
selector: 'app-sidenav',
templateUrl: './sidenav.component.html',
styleUrls: ['./sidenav.component.scss']
})
export class SidenavComponent implements OnInit {
public isScreenSmall! : boolean;
users! : Observable<User[]>;
//tambahkan viewchild untuk akses sidenav
@ViewChild(MatDrawer) drawer! : MatDrawer;
//inject router
constructor(private breakpointObs : BreakpointObserver, private userSrv : UserService, private router: Router) { }
ngOnInit(): void {
this.breakpointObs
.observe([`(max-width: ${SMALL_WIDTH_BP}px)`])
.subscribe((state: BreakpointState)=>{
this.isScreenSmall = state.matches;
});
this.users = this.userSrv.users;
this.userSrv.loadAllUser();
this.users.subscribe(data =>{
//modifikasi untuk menampilkan user idx pertama
if(data.length>0) this.router.navigate(['/contactmanager', data[0].id]);
});
//menutup sidenav setelah user dipilih.
this.router.events.subscribe(()=>{
if(this.isScreenSmall){
this.drawer.close();
}
});
}
}
