mgeno
mgeno

Reputation: 191

Using ActivatedRoute within another Service

I would like to use the ActivatedRoute service within another service. However, within my service the ActivatedRoute service is watching the main App component and none of route parameter changes are being emitted from the observable. If I instead watch the route parameters from within a component in the same module, the ActivatedRoute service functions as expected.

Here is a simplified version of my directory and it

app/
├──app.module.ts          <- RouterModule Imported Here
├──app.component.ts
|
└──other-module/
   ├──other.module.ts     <- other.service provided here
   ├──other.component.ts  <- ActivatedRoute works as expected
   └──other.service.ts    <- ActivatedRoute watches App component

Here is a simplified version of my routes configuration:

export const routes: Routes = [
  { path: '', component: App },
  { path: 'other/:id', component: Other }
];

Could anyone provided some with how to properly handle and inject the services so that I can use the ActivatedRoute service from within another service.

Thanks.

Upvotes: 4

Views: 3919

Answers (2)

jmq
jmq

Reputation: 2389

In Angular 2.1.0, I have this simplistic usage of ActivatedRoute working (note that I'm using queryParams instead of params since I'm wanting to match something like ?name=Joe. Reference https://stackoverflow.com/a/39146396/4185989 for more info on that.)

EDIT: It's possible that my solution below is only because I am looking for queryParams, rather than a component URL's fragment like :id - I see there's an Angular issue filed at https://github.com/angular/angular/issues/11023 for the latter. Leaving my answer available nevertheless, for people that might be wanting queryParams like I was.

user.service.ts

import {Injectable} from "@angular/core";
import {ActivatedRoute} from "@angular/router";

import {Subscription} from "rxjs/Rx";
import {UserModel} from "./shared/user.model";

@Injectable()
export class UserService {
  protected user: UserModel;
  protected subscription: Subscription;

  constructor(protected activatedRoute: ActivatedRoute) {
    this.subscription = this.activatedRoute.queryParams.subscribe(
      (queryParams: any) => {
        if (queryParams.name) {
          this.setUser(queryParams.name);
        }
      }
    )
  }

  setUser(name) {
    this.user = new UserModel(name);
    console.log('Setting user', this.user);
  }

}

user.model.ts

import {Injectable} from "@angular/core";

@Injectable()
export class UserModel {

  constructor(public name: string) {}
}

user.module.ts

import { NgModule } from '@angular/core';
import {UserService} from "./user.service";

@NgModule({
  imports: [
  ],
  declarations: [
  ],
  exports: [
  ],
  providers: [
    UserService
  ]
})
export class UserModule { }

app.component.ts

import { Component } from '@angular/core';
import {UserService} from "./core/user/user.service";

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor(
    protected userService: UserService
  ) {
  }
}

Upvotes: 2

JeanPaul A.
JeanPaul A.

Reputation: 3724

I ran into a similar problem, and couldn't find a proper solution to it. As a matter of fact I've just opened a bug report (see https://github.com/angular/angular/issues/12938), to either get it checked or otherwise get some direction on how we should tackle this issue.

As a temporary work around however, I did manage to achieve a navigation to a url relative to the current one (not levels deeper) from a service using the following

this.router.navigate([ this.router.url.concat('/relativepath') ]);

Note that this is a really really hacky temporary workaround and should be replaced to the proper

this.router.navigate(['./relativepath'], {relativeTo: this.activatedRoute}) 

should this feature become supported.

Upvotes: 0

Related Questions