So I have an API that I am trying to consume data from. The data being retuned:
Org
baseId: 1
createdAt: "2018-11-14T04:35:35.345Z"
id: 1
isActive: true
orgName: "Test Organization 1"
orgOwner: 2
subscriptionCode: "testorg1"
updatedAt: "2018-11-14T04:35:35.34
Base
bandwidthApiSecret: "xxxxxx"
bandwidthApiToken: "t-xxxxxx"
bandwidthUserId: "u-xxxxxx"
baseName: "Test AFB 1"
basePhoneNumber: "+18442367381"
createdAt: "2018-11-14T04:35:35.123Z"
id: 1
isActive: true
updatedAt: "2018-11-14T04:35:35.123Z"
What I would like to do, but fail to comprehend is using rxjs operations to insert the organization where needed. So if a base has one or more organizations it should be inserted into the bases. Here are my interfaces:
Base Interface
import { Organization } from './organization';
import { BaseManager } from './base-manager';
export interface Base {
id: number;
basePhoneNumber: string;
baseName: string;
bandwidthUserId: string;
bandwidthApiToken: string;
bandwidthApiSecret: string;
createdAt?: Date;
updatedAt?: Date;
orgs?: Organization;
managers?: BaseManager;
}
Org Interface
export interface Organization {
id: number;
orgName: string;
orgOwner: string;
baseId: number;
subscriptionCode: string;
isActive: boolean;
createdAt: Date;
updatedAt: Date;
}
I found this JSBin that sort of looks like it's doing what I need to accomplish. Due to my lack of comprehension of the subject I am failing to make it work. Here's a snippet of my Angular Component:
import { Component, OnInit } from '@angular/core';
import { Base } from 'src/app/core/interfaces/base';
import { BaseService } from 'src/app/core/services/base.service';
import { OrgService } from 'src/app/core/services/org.service';
import { Organization } from 'src/app/core/interfaces/organization';
import { switchMap } from 'rxjs/operators';
@Component({
selector: 'app-base-list',
templateUrl: './base-list.component.html',
styleUrls: ['./base-list.component.css']
})
export class BaseListComponent implements OnInit {
bases: Base[];
orgs: Organization[];
constructor(private baseService: BaseService, private orgService: OrgService) { }
ngOnInit() {
this.loadOrgs();
this.loadBases();
}
loadBases() {
this.baseService.getAllBases()
.subscribe(
res => {
this.bases = res['bases'];
console.log(this.bases);
}
);
}
// loadBases(): Base[] {
// this.baseService.getAllBases()
// .subscribe(
// res => {
// this.bases = res['bases'].pipe(
// switchMap( base => {
// return this.getOrg(base.id).map(
// base => {
// return Object.assign(base, {base, {org: this.orgs});
// }
// )
// })
// );
// });
// }
loadOrgs() {
this.orgService.getOrgs()
.subscribe(
res => {
this.orgs = res['orgs'];
console.log(this.orgs);
}
);
}
getOrg(baseId) {
this.bases.filter(base => base.id === baseId);
}
}
Any help on the matter would be greatly appreciated.
Cheers,
Coach
There are three issues: First,
res['bases']
is not an Observable and therefore can't be piped. This function invocation is not possible:Second, you are trying to assign the Observable to the property
this.bases
which has the typeBase[]
and notObservable<Base[]>
. The assignment would therefore not be valid.Third, even if
res['bases']
were an Observable, you are never subscribing to it, so it won't ever emit any notifications.The solution is one the one hand to not subscribe before the
switchMap
, but afterwards and on the other hand to correctly handle the array collection, e.g. withzip
. This is how it would look like:Now, another issue is that you aren't waiting for
loadOrgs
to compete before trying to load the bases. This should also be concatenated like this:And in
ngOnInit
:As a rule of thumb, be sure to always subscribe to your Observables, otherwise you won't actually execute anything. There are some pipes that do subscribe to inner Observables, like
switchMap
, but there must actually be a Subscriber for theswitchMap
pipe as well in order for it to take effect.