Blog>
Snippets

Combining Multiple Stores with Akita

Present a code example of combining data from multiple Akita stores into a single observable stream using RxJS operators in the context of an Angular application.
import { Injectable } from '@angular/core';
import { combineLatest } from 'rxjs';
import { Store, Query } from '@datorama/akita';

export interface User {
  id: number;
  name: string;
}

export interface Product {
  id: number;
  title: string;
}

@Injectable({ providedIn: 'root' })
export class UsersStore extends Store<User> {
  constructor() {
    super();
  }
}

@Injectable({ providedIn: 'root' })
export class UsersQuery extends Query<User> {
  constructor(protected store: UsersStore) {
    super(store);
  }

  selectUsers() {
    return this.select();
  }
}

@Injectable({ providedIn: 'root' })
export class ProductsStore extends Store<Product> {
  constructor() {
    super();
  }
}

@Injectable({ providedIn: 'root' })
export class ProductsQuery extends Query<Product> {
  constructor(protected store: ProductsStore) {
    super(store);
  }

  selectProducts() {
    return this.select();
  }
}
This code snippet contains the setup for two Akita stores and queries: UsersStore and ProductsStore. Both are decorated with @Injectable, meaning they can be injected as dependencies in Angular components or services. The `UsersQuery` and `ProductsQuery` classes can be used to select data from the stores.
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { combineLatest } from 'rxjs';
import { UsersQuery } from './users.store';
import { ProductsQuery } from './products.store';

@Component({
  selector: 'app-user-products',
  template: `<div *ngFor="let item of combinedData$ | async">{{item | json}}</div>`
})
export class UserProductsComponent implements OnInit {
  combinedData$: Observable<any>;

  constructor(private usersQuery: UsersQuery, private productsQuery: ProductsQuery) { }

  ngOnInit() {
    this.combinedData$ = combineLatest([
      this.usersQuery.selectUsers(),
      this.productsQuery.selectProducts(),
    ]).pipe(
      map(([users, products]) => ({ users, products })) // Combines user data and product data
    );
  }
}
This code snippet defines an Angular component that combines data from the UsersQuery and ProductsQuery using RxJS's `combineLatest` function. The combined data is stored in `combinedData$`, which is an Observable stream and can be subscribed to or used with the `async` pipe in the component template. The `map` function is used to transform the data emitted by the combined observables into a single object with `users` and `products` as properties.