Here is what I did (Pure RxJS implementation using ReplaySubject
):
The common service where the param (eg. paramThing
) will be stored (as an observable):
@Injectable({
providedIn: "root",
})
export class MyService {
// use ReplaySubject to store/observe the paramThing
paramThing$ = new ReplaySubject<string | null>(1);
constructor() {}
}
Then in the component where ActivatedRoute
gives proper value:
@Component({
selector: "app-xxx",
templateUrl: "./xxx.component.html",
styleUrls: ["./xxx.component.scss"],
})
export class XxxComponent implements OnInit, OnDestroy {
private subs: Subscription[] = [];
constructor(
private readonly actRoute: ActivatedRoute,
private readonly myService: DashService
) {}
ngOnInit(): void {
const subscription = this.actRoute.paramMap
.pipe(map((parameters) => parameters.get("paramThing")))
.subscribe((paramThingValue) => {
this.myService.paramThing$.next(paramThingValue); // <=== this does the trick
});
this.subs.push(subscription);
}
ngOnDestroy(): void {
for (const item of this.subs) item.unsubscribe();
this.subs = [];
// if you need, you can unset the value when component goes out of scope
this.myService.paramThing$.next(null);
}
}
Then in any consuming component/service, you can use the MyService
to get the value of paramThing:
Example service where I need the paramThing
.
import { lastValueFrom, take, switchMap } from "rxjs";
@Component({
selector: "app-ccc",
templateUrl: "./ccc.component.html",
styleUrls: ["./ccc.component.scss"],
})
export class CccComponent implements OnInit {
constructor(
private readonly myService: MyService
) {}
async ngOnInit() {
const paramThing = await lastValueFrom(this.myService.paramThing$.pipe(take(1)));
// paramThing:null | string
// or if you want an observable chain for paramThing
this.myService.paramThing$.pipe(
switchMap(paramThing => {
return anotherPromiseOrObservableChain;
}),
// ...
).subscribe(...)
}
}