2

We build a webapp where the user has to click through lists to get to a certain edit view. E.g. from the landing page, the user selects a client, then an agent and then gets to the edit view of that agent. The URL in that case would hold the IDs: /client/4/agent/7/edit. @ngrx/router-store is used to handle URL-changes, so when the URL above is accessed directly, the edit view appears and works fine.

The app also contains a breadcrumb, which shows not the ID but the names of the pieces of path: Client: Company > Agent: Postal > Edit when client = { id: 4, name: 'Company' } and agent = { id: 7, name: 'Postal' }. We usually fetch this data(client and agent) when the correspondent list entry is clicked.

However, when a URL like /client/4/agent/7/edit is accessed directly, there is no client-Object stored that contains the name. How can I fetch the object that belongs to a route when a URL is accessed directly in a reduxy way? I know how I could hack this into the app, but the dataflow should remain nice and clean reduxy.

Things I've considered:

  • Checking the existence of client, agent etc. in every component and fetching them, if they do not exist. This could be a lot of overhead and also, additionally the logic should go into selectors which cannot trigger an action.
  • Using a service for checking if the data is already there - if not, load it. Would be checked on every URL change and could also slow down the application.
  • Trigger the fetching of data on the initial load of the application - where to do that? AppComponent?

I'm also open to restructuring the whole application (use another routing, introduce @ngrx/effects, redefine the API etc.)

Florian Gössele
  • 4,376
  • 7
  • 25
  • 49
  • Have you tried to use "ngrx/router-store" ?!? it will listen to every change on the URL and add into your redux store. – Denison Luz Feb 05 '19 at 14:09
  • I write in the first paragraph that we use router-store. The problem is: where should I listen to router events - in the Breadcrum Reducer? And how can I know if the data (`client` and `agent`) is already in the state? – Florian Gössele Feb 05 '19 at 14:48
  • Sorry @frot.io, I've missed that you are already using @ngrx/router-store. This a really good example of something similar to what you are trying to do https://github.com/BioPhoton/angular-ngrx-refactoring/wiki/4.-Handling-router-state-with-@ngrx-router-store – Denison Luz Feb 05 '19 at 17:09

1 Answers1

1

One way to achieve this is to create a custom data service

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { DefaultDataService, HttpUrlGenerator, Logger } from '@ngrx/data';
import { Hero } from '../../model/job/hero';

@Injectable({
  providedIn: 'root'
})
export class HeroDataService  extends DefaultDataService<Hero> {

  constructor(http: HttpClient, httpUrlGenerator: HttpUrlGenerator, logger: Logger) {
    super('Hero', http, httpUrlGenerator);
    logger.log('Created custom Hero EntityDataService');
  }

  public setEntitiesUrl(entitiesUrl) {
    this.entitiesUrl = entitiesUrl;
  }

  public setEntityUrl(entityUrl) {
    this.entityUrl = entityUrl;
  }

}

Then register it in your entity store module:

  constructor(
    heroDataService: HeroDataService
    ) {
    entityDataService.registerService('Hero', heroDataService);
  }

Then in your component, set your custom path before making you call your EntityCollectionService (ie, for entityCollection)

this.heroDataService.setEntitiesUrl('myCustomPath');
this.heroes$ = this.heroService.getAll();

For single entities call setEntityUrl method instead.

lionelto
  • 81
  • 5