I am using a angular service to pass the data between components. I would like this service to hold the 4 ids uniId, schoolId, classId and studentId. There are 4 components: Component 1 setting uniId, Component2 setting schoolId using uniId, Component 3 setting classId using uniId and schoolId and Component 4 setting studentId using uniId, schoolId and classId. I want to achieve following:
Model class
export interface GlobalData {
uniId: number;
schoolId: number;
classId: number;
studentId: number;
}
Service Class
import { Injectable } from '@angular/core';
import { GlobalData } from 'src/models/GlobalData';
import { BehaviorSubject, Observable, Subject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class GlobaldataService {
private globalDataSubject = new Subject<GlobalData>();
constructor() { }
public getGlobalData(): Observable<GlobalData> {
return this.globalDataSubject.asObservable();
}
public setGlobalData(globalDataObj: GlobalData) {
return this.globalDataSubject.next(globalDataObj);
}
}
Component 3
globalDataObject: GlobalData;
uniId: number = 0;
schoolId: number = 0;
constructor(private router: Router, private route: ActivatedRoute, private globalDataService: GlobaldataService) {
}
ngOnInit() {
this.route.queryParams.subscribe(params => {
this.uniId = params['uniId'];
this.schoolId = params['schoolId'];
})
this.globalDataService.setGlobalData({
uniId: this.uniId,
schoolId: this.schoolId,
classId: 0,
studentId: 0
});
this.globalDataService.getGlobalData().subscribe(x =>
this.globalDataObject = x)
}
Component 3 View
<li class="dds__breadcrumb__item" [routerLinkActive]="['link-active']">
<a [routerLink]="['/unis']">Universities</a>
</li>
<li class="dds__breadcrumb__item" [routerLinkActive]="['link-active']">
<a [routerLink]="['/schools']" [queryparams]="{uniId: this.uniId}">Schools</a>
</li>
<li class="dds__breadcrumb__item" [routerLinkActive]="['link-active']">
<a [routerLink]="['/classes']">Classes</a>
</li>
In Component 3, when I click on first link it would show all unis, when I click on the second link it would show all schools in the uni whose id is selected and classes would npt navigate to anything as Component 3 is Classes.
I am not getting data in service and the navigation does not concatenate ids. Can anyone please help on this.
Three problems:
You're setting your global data outside of your params subscription.
Observable subscriptions don't trigger change detection unless you're using the async
pipe. So you need to force it with ChangeDetectorRef
.
constructor(private changeDetectorRef: ChangeDetectorRef) {}
async ngOnInit() {
this.route.queryParams.subscribe((params) => {
this.uniId = params['uniId'];
this.schoolId = params['schoolId'];
this.globalDataService.setGlobalData({
uniId: this.uniId,
schoolId: this.schoolId,
classId: 0,
studentId: 0,
});
this.globalDataService.getGlobalData().subscribe((x) => {
this.globalDataObject = x;
this.changeDetectorRef.detectChanges();
});
});
}
queryParams
has a capital P...
<li class="dds__breadcrumb__item" [routerLinkActive]="['link-active']">
<a [routerLink]="['/schools']" [queryParams]="{ uniId: this.uniId }"
>Schools</a
>
</li>
...
This can all be rewritten much simpler, there's no need for observables if you're simply setting and getting values.
Service
@Injectable({
providedIn: 'root',
})
export class GlobaldataService {
globalData?: GlobalData;
}
Component 3
get uniId() {
return this.globalDataService.globalData?.uniId;
}
constructor(
private route: ActivatedRoute,
private globalDataService: GlobaldataService
) {}
ngOnInit() {
const params = this.route.snapshot.queryParams;
this.globalDataService.globalData = {
uniId: params['uniId'],
schoolId: params['schoolId'],
classId: 0,
studentId: 0,
};
}
<li class="dds__breadcrumb__item" [routerLinkActive]="['link-active']">
<a [routerLink]="['/unis']">Universities</a>
</li>
<li class="dds__breadcrumb__item" [routerLinkActive]="['link-active']">
<a [routerLink]="['/schools']" [queryParams]="{ uniId }">Schools</a>
</li>
<li class="dds__breadcrumb__item" [routerLinkActive]="['link-active']">
<a [routerLink]="['/classes']">Classes</a>
</li>
Although I don't see a point in passing queryParams
through the template when you can just inject the service.