Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve a route param using Injector.get(ActivatedRoute)?

Tags:

angular

I'm new to Angular. My goal is to have a BaseDetailComponent which can be extended by "detail" components (those which show a single data object's fields). Since the parent class' constructor will receive a service instance and other params, I can't use normal dependency injection in the constructor. Therefore, I need to manually inject the application injector in BaseDetailComponent. I tried the code below. There is an InjectorManager, which has its injector set by the global AppModule. Then BaseDetailComponent retrieves InjectorManager's injector and uses it to get the app's ActivatedRoute instance. But, for some reason, activatedRoute.snapshot.params.id is undefined. And this is my issue. I need to access route params on a class where ordinary constructor dependency injection is unavailable.

export class InjectorManager {

  private static _injector: Injector;

  static get injector(): Injector {
    return this._injector;
  }

  static set injector(value: Injector) {
    this._injector = value;
  }
}

export class AppModule {

  constructor(
    injector: Injector
  ) {
    InjectorManager.injector = injector;
  }
}

@Component({template: ''})
export class BaseDetailComponent {

  protected activatedRoute: ActivatedRoute;

  constructor(
    private service: BaseService<DtoType>
  ) {
    this.activatedRoute = InjectorManager.injector.get(ActivatedRoute);
  }

  ngOnInit() {

    this.service.findById(this.activatedRoute.snapshot.params.id)
      .subscribe(...);
  }
}

like image 644
Carlos Avatar asked Sep 01 '25 04:09

Carlos


2 Answers

This is a similar question as Parent components gets empty Params from ActivatedRoute.

The Angular documentation for ActivatedRoute states (my emphasis):

Contains the information about a route associated with a component loaded in an outlet.

There is also an issue of feature request on Angular's GitHub repo asking for a solution, that states (my emphasis):

When using a parametrized route which targets a component, only this component can access those parameters.

Thus, you are encountering an expected behavior. A comment on that issue states that each component receives its own ActivatedRoute (it does not work as singleton like other injected classes).

On that same GitHub issue, the proposed solution is to inject a Router and check for the NavigationEnd events:

router.events.filter(e => e instanceof NavigationEnd).forEach(() => {
  // inspect the state on router.routerState
})

For a complete example check the file src/app.ts on this plunkr provided by @brandonroberts on the GitHub issue: http://plnkr.co/edit/pHd89K?p=preview

like image 158
Dinei Avatar answered Sep 02 '25 17:09

Dinei


Firs you can inject ActivatedRoute just by placing it in the constructor params.

constructor(
    private service: BaseService<DtoType>,
    protected activatedRoute: ActivatedRoute;
) {}

Second you have to subscribe to this.activatedRoute.params as it can change after the component is initialized:

this.activatedRoute.params.pipe(switchMap(({id}) => this.service.findById(id)).Subscribe(...)
like image 24
Stanisalv Dontsov Avatar answered Sep 02 '25 18:09

Stanisalv Dontsov