ngrx data - collection service and data service, custom endpoint observable

245 Views Asked by At

I needed a custom PUT request related to my entity in ngrx/data, I would like to show it as I am not certain it is accurate... Say a I have a movie library and I can add tags to movies with PUT request.

My data service:

export class MovieDataService extends DefaultDataService<typeof Movie> {
  constructor(http: HttpClient, httpUrlGenerator: MovieHttpUrlGenerator, logger: Logger) {
    super('Movie', http, httpUrlGenerator);
    logger.log('Created custom Movie EntityDataService');
  }

  // CUSTOM METHODS APART FROM AUTO-CRETED BY COLLECTION SERVICE 
  // Further handled in collection service
  addTagToMovie(movieId: number, tagId: number) {
    return this.execute(
      'PUT', 
      `https://external-api.com/movie/${movieId}/add_tag/${tagId}/`,
    )
  }

}

Collection-service

 constructor(
    EntityCollectionServiceFactory: EntityCollectionServiceFactory,
    private movieDataService: movieDataService,
  ) {
    this.movieCollectionService = EntityCollectionServiceFactory.create<typeof Movie>('Movie');
  }

  getMovies() { this.movieCollectionService.getAll(); }

  addTagToMovie(movieId: number, tagId: number) {
    if (movieId && tagId) {
      this.movieCollectionService.setLoaded(false)
      this.movieCollectionService.setLoading(true)

      this.movieDataService.addTagToMovie(movieId, tagId).pipe(
        tap((updatedMovie: typeof Movie) => {
          this.movieCollectionService.updateOneInCache(updatedMovie)
          this.movieCollectionService.setLoading(false)
          this.movieCollectionService.setLoaded(true)
        })
      ).subscribe()
    }

  }

Is this an appropriate way to achieve this? Also, will the subscribe on addTagToMovie cause a memory leak? Without it, it does not trigger, other collection services methods need no subscribing (for instance getAll()) is it possible to implement it withou subscriibng as well?

I tried the described above.

1

There are 1 best solutions below

0
Naren Murali On

My understanding is that the subscribe need not happen on the service, instead just return an observable on the service, which will get subscribed on the component.

Collection-service

 constructor(
    EntityCollectionServiceFactory: EntityCollectionServiceFactory,
    private movieDataService: movieDataService,
  ) {
    this.movieCollectionService = EntityCollectionServiceFactory.create<typeof Movie>('Movie');
  }

  getMovies() { this.movieCollectionService.getAll(); }

  addTagToMovie(movieId: number, tagId: number) {
    let output$ = of([]);
    if (movieId && tagId) {
      this.movieCollectionService.setLoaded(false)
      this.movieCollectionService.setLoading(true)

      output$ = this.movieDataService.addTagToMovie(movieId, tagId).pipe(
        tap((updatedMovie: typeof Movie) => {
          this.movieCollectionService.updateOneInCache(updatedMovie)
          this.movieCollectionService.setLoading(false)
          this.movieCollectionService.setLoaded(true)
        })
      )
    }
    return output$;
  }

In the component you can do

private subscription: Subscription = new Subscription();

ngOnInit() {
    this.subscription.add(
        this.collectionService.addTagToMovie(1,2).subscribe()
    );
}

ngOnDestroy() {
    this.subscription.unsubscribe();
}