1

I am using a few backend services to populate three columnns with Material Designs data table. I am using an observable to populate the data Source data. but how do I include the data from the other services. So far I am only able to use data from one Service. My thought process was to use a .push to the data Source.

dataSource = []

constructor(public data: xService, public otherData: yService) { }

submit() {
    this.data.getUsers().subscribe(data => {
        this.dataSource = data.rows;
    });

    this.otherData.getUnitAssignments().subscribe(otherData => {
        this.dataSource.push({ assignments: otherData });
    });
}

Services Files

export interface xresponse {
  rows: Array < string > ,
}
constructor(private http: HttpClient) {}

getUsers(): Observable<xResponse> {
  return this.http.get<xResponse>('/services/****/user/j**/******');
}

other Service

export interface yResponse {
    rows: Array<string> ,
}

@Injectable({
    providedIn: 'root'
})
export class yService {

    constructor(private http: HttpClient) {}

    getyInfo(): Observable<yResponse> {
        return this.http.get<yResponse>('/services/c***/user/j****/*****');
    }
}
Tushar Walzade
  • 3,737
  • 4
  • 33
  • 56
Flash
  • 924
  • 3
  • 22
  • 44

3 Answers3

3

It seems that you need the response from both the services at once; if it is the case, RxJS ForkJoin is your friend! You can use forkJoin as follows -

import { forkJoin } from 'rxjs';

submit() {
    const combined = forkJoin([
        this.data.getUsers(),
        this.otherData.getUnitAssignments()
    ]);
    combined.subscribe((response) => {
        // you will get 2 arrays in response
        this.dataSource.push(response[0].rows);
        this.dataSource.push(response[1].rows);
    });
}
  • FYI, forkJoin waits for each http request to complete and group’s all the observables returned by each http call into a single observable array and finally return that observable array.
Tushar Walzade
  • 3,737
  • 4
  • 33
  • 56
  • Thanks the only thing is when I try to access them from the coulumns the way the data table works it doesnt seem to be working: ` title1 title2 {{second[1].rows}} `
    {{first[0].rows}}
    – Flash Mar 04 '19 at 14:04
  • Try to debug your code & *ensure that you are putting right responses in `dataSource`*. I just shown `response[x].rows`, but it may be different in your case – Tushar Walzade Mar 04 '19 at 14:05
1

One solution is to use the RxJs combineLatest operator to combine the responses from all services:

submit() {
  combineLatest(
    this.service1.getData(),
    this.service2.getData(),
    this.service3.getData()
  ).subscribe(allData => ...)
}

Edit: Upon further thought, I suggest that for this use case, where each HTTP request should complete, you use forkJoin as answered by Tushar Walzade. This SO answer gives a concise explanation of what the difference is between forkJoin and combineLatest.

Sam Herrmann
  • 6,293
  • 4
  • 31
  • 50
  • Thanks Just tested it out and it combined them for me. but When I try to access the data for service1 for column 1 and service2 for coulumn 2 in the table I'm having trouble accessing the data for of [0] and of [1]. but I'm still debugging. I think its relatd to the publick interface I defined in my services – Flash Mar 04 '19 at 13:44
1

You could use RxJs forkJoin operator. This way you will construct your dataSource only when all responses will be received (as it said in official docs it works similar to Promise.all):

ngOnInit(): void {
    forkJoin([this.data.getUsers(), this.otherData.getUnitAssignments()])
        .subscribe(result => {
            this.firstRequestResult = result[0];
            this.secondRequestResult = result[1];
            //building your dataSource here

        });
}
Petr Pokrovskiy
  • 725
  • 7
  • 17