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.baseswhich 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
loadOrgsto 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 theswitchMappipe as well in order for it to take effect.