У цьому прикладі розглядається ситуація, яка часто зустрічається в багатьох додатках, де є два різні, але пов'язані набори даних, які потрібно отримати з різних API та відобразити разом. Важливо, що відображення цих даних повинно бути таким, щоб зв'язок між ними був чітко видимий.
Наприклад, потрібно відобразити основні дані 10 користувачів у таблиці. Ці дані доступні через фіктивний API, а також необхідно показати задачі (ToDos), створені кожним користувачем. Деталі задач доступні через інший API.
Ми створили інтерфейс UserModel для моделювання даних користувачів, що виглядає так:
export interface UserModel {
id: number,
name: string,
username: string,
email: string,
address: AddressModel,
phone: string,
website: string,
company: CompanyModel
}
Також для задач кожного користувача ми створили інтерфейс ToDoModel:
export interface ToDoModel {
userId: number,
id: number,
title: string,
completed: boolean
}
Зв'язок між цими двома наборами даних — це id користувача. Ми відобразимо кілька деталей користувача, таких як id та name у UserModel. Використовуватимемо userId з ToDoModel для отримання задач, створених кожним користувачем.
Нижче представлений скріншот того, що ми хочемо досягти.
Для отримання цих даних ми використовуємо сервіс DataService:
export class DataService{
constructor(private http:HttpClient){}
getUsers():Observable{
return this.http.get < UserModel[]>(‘https://jsonplaceholder.typicode.com/users')
}
getToDos(): Observable{
return this.http.get(‘https://jsonplaceholder.typicode.com/todos')
}
}
У класі AppComponent ми паралельно викликаємо два API за допомогою forkJoin з бібліотеки RXJS в методі ngOnInit:
this.data$ = forkJoin([
this.service.getUsers().pipe(this.handleError().bind(this)),
this.service.getToDos().pipe(this.handleError().bind(this)),
])
Для обробки помилок ми створюємо метод handleError():
handleError() {
let that = this;
return function (observable: Observable) {
return observable.pipe(
catchError((err: HttpErrorResponse) => {
that.errorSub$.next(err.message);
return of(null);
}),
takeUntil(that.destroy$)
);
};
}
У методі map ми об'єднуємо дані від обох API, створюючи новий масив об'єктів, кожен з яких відповідає інтерфейсу UserToDoModel:
map(([users, todos]) => {
let result: UserToDoModel[] = users.map((user: UserModel) => {
return {
userDetail: user,
todos: todos.filter((x: ToDoModel) => x.userId == user.id),
};
});
return result;
}),
Ось інтерфейс UserToDoModel:
export interface UserToDoModel {
userDetail: UserModel;
todos: ToDoModel[];
}
Тепер у нас є масив об'єктів UserToDoModel, який містить інформацію про кожного користувача разом із його задачами.
Ми підписуємося на обсервабель data$ в шаблоні компонента за допомогою async pipe і відображаємо деталі користувачів та їхні задачі.
У результаті ми маємо робочий приклад, де дані користувачів і задач відображаються в таблиці, при цьому зв'язок між ними чітко видно.
Дякуємо, що стали частиною нашої спільноти!
Перекладено з: Angular for Beginners: Combining different sets of related data for display using RXJS