Komposisi Data Dalam Angular Dengan Menggunakan RxJS
Pendahuluan
Pada artikel ini kita akan melihat cara menyusun data suatu platform agar mudah diproses.
Kita ambil contoh sebuah aplikasi yang perlu menampilkan informasi siswa dan kelasnya masing-masing, dalam hal ini kita perlu mengolah beberapa sumber data menjadi satu.
Apa itu komposisi data dalam Angular?
Secara sederhana kita akan mengatakan bahwa komposisi data terdiri dari menggabungkan dua atau lebih sumber data untuk membuat satu sumber yang dapat dimanipulasi.
Kami akan menjalankan demo kami dengan aplikasi yang terhubung dengan firebase.
2. Pemulihan sumber data
Tujuannya di sini adalah untuk mendapatkan semua sumber data yang kita butuhkan dalam aplikasi kita.
Model
Mengetahui konteks aplikasi kami, kami akan membuat 2 antarmuka yang akan mewakili 2 jenis data yang akan kami manipulasi:
classes.model.ts
export interface Classe {
uid: string;
name: string;
titulaire: string;
createdAt: Date;
updatedAt: Date | null;
}
students.model.ts
export interface Student {
uid: string;
name: string;
phoneNumber: string;
emailAddress: string;
classe: string;
createdAt: Date;
updatedAt: Date | null;
}
student.service.ts
Layanan ini akan memungkinkan kami untuk mengumpulkan semua informasi yang berkaitan dengan siswa.
import {Injectable} from '@angular/core';
import {Student} from '../models/students.model';
import {FirestoreService} from './firestore.service';
import {Observable, catchError} from 'rxjs';
@Injectable({providedIn: 'root'})
export class StudentService{
handlerError: any = '';
students$ = Observable<Student[]> = this.firestoreService.col$('students/')
.pipe(
tap(console.log),
catchError(this.handlerError)
);
constructor(private firestoreService: FirestoreService){}
}
siswa.komponen.ts
Tujuan dari komponen ini adalah untuk mengambil informasi siswa dari layanan yang dibuat sebelumnya dan menyimpannya di properti $ siswa lokal.
import {Component, OnInit} from '@angular/core';
import {catchError, of} from 'rxjs';
import {StudentService} from '../services/student.service';
export class GroupsComponent implements OnInit{
errorMessage = '';
students$ = this.studentService.students$
.pipe(
catchError((error) => {
this.errorMessage = error;
return of(null);
})
);
constructor(private studentService: StudentService) {}
}
student.component.html
Dalam pandangan kami, kami akan mengikat ke yang dapat diamati dengan menentukan pipa async yang secara otomatis akan berlangganan dan berhenti berlangganan ke yang dapat diamati.
<div *ngIf="students$ | async as students">
<button type="button" *ngIf='let student of students'>
{{student.name | titlecase}} - {{student.class}}
</button>
</div>
Kami akan menambahkan strategi deteksi perubahan OnPush ke komponen kami yang akan meminimalkan siklus deteksi perubahan.
3. Komposisi data
Komposisi terdiri dari menggabungkan informasi yang sama dengan data yang telah kami kumpulkan.
Dalam informasi siswa, kami memiliki UID kelasnya yang merupakan string yang tidak dapat dibaca tetapi tujuan kami di sini adalah untuk mengambil juga informasi kelas ini dan menampilkan misalnya namanya.
Pemulihan kelas akan dilakukan dengan cara yang sama seperti yang dilakukan pada siswa.
classes.service.ts
import {Injectable} from '@angular/core';
import {Classe} from '../models/classes.model';
import {FirestoreService} from './firestore.service';
import {Observable, catchError} from 'rxjs';
@Injectable({providedIn: 'root'})
export class ClasseService{
handlerError: any = '';
classes$ = Observable<Classe[]> = this.firestoreService.col$('classes/')
.pipe(
tap(console.log),
catchError(this.handlerError)
);
constructor(private firestoreService: FirestoreService){}
}
Kami kemudian akan menggunakan combineLatest untuk menggabungkan data siswa kami dengan data kelas kami untuk mendapatkan flow data baru.
student.service.ts
studentsWithClasses$ = combineLatest(
this.students$
this.classeServices.classes$
).pipe(
map(([students, classes]) => {
return students.map(student=> ({
...student,
classe: classes.find(classe => classe.uid === student.uidClasse).name
} as Student));
})
);
students.component.ts
Kami sekarang akan mengambil studentsWithClasses$ yang berisi informasi siswa dengan nama kelas.
import {Component, OnInit} from '@angular/core';
import {catchError, of} from 'rxjs';
import {StudentService} from '../services/student.service';
export class GroupsComponent implements OnInit{
errorMessage = '';
students$ = this.studentService.studentsWithClasses$
.pipe(
catchError((error) => {
this.errorMessage = error;
return of(null);
})
);
constructor(private studentService: StudentService) {}
}
Dan kita tidak perlu mengubah view karena sudah tertaut ke student$.
Kami juga dapat menggabungkan flow kami sebagai tanggapan atas tindakan pengguna. Untuk ini kita akan membuat Action Stream.
student.service.ts
private studentSelectedAction = new BehaviorSubject<string>(null);
studentSelectedAction$ = this.studentSelectedAction.asObservable();
Dan kami akan menggabungkan flow Tindakan kami dengan flow data kami dan mengambil data setiap kali tindakan dilakukan.
selectedStudent$ = combineLatest(
this.studentSelectedAction$,
this.studentsWithClasses$
).pipe(
map(([selectedStudentUid, students]) => {
return students.find(student => student.uid === selectedStudentUid);
}
)
);
Kami akan menyiapkan metode yang akan memastikan bahwa kami memancarkan tindakan pengguna.
private changeSelectedStudent(selectedStudentUid: string | null): void {
this.studentSelectedAction.next(selectedStudentUid);
}
onSelect(studentUid: string): void {
this.changeSelectedStudent(studentUid);
}
student.komponen.ts
Di dalam komponen, kita memiliki dua cara untuk memanggil metode onSelect()
-
Jika kita tetap di komponen yang sama: buat metode yang memanggil metode di bawah aksi
restoreStore(idStudent: string): void { this.studentService.onSelect(idStudent); }
-
Jika kita mengubah komponen: panggil metode di komponen baru ngOnInit()
this.route.paramMap.subscribe( idGroup => { this.uidStudent = idStudent.get('idStudent'); this.studentService.onSelect(this.idStudent); )
Ringkasan
Panduan ini telah menunjukkan cara menggabungkan dua flow data menjadi satu dengan RxJS dan mengoptimalkan aplikasi kita. Dimungkinkan untuk melakukan ini dengan tiga dan lebih banyak lagi; Jika Anda ingin mempelajari lebih lanjut tentang Angular, kunjungi dokumentasi resmi.