Home > Back-end >  By making API calls in Angular (8) trying to get the count match with the data
By making API calls in Angular (8) trying to get the count match with the data

Time:04-05

It might seem stupid to some but most of my confusion is caused by my frustration.

I am making API calls to some endpoints from this page: https://beacon-network.org/#/developers/api/beacon-network#bn-beacons

I have no problem at the service I am able to get the data. My service.ts:

import {HttpClient} from '@angular/common/http';
import {Injectable} from '@angular/core';
import {Observable} from 'rxjs';
import {Organization} from './organization'; // it is an interface that has id and name
import {Beacons} from './beacons'; // it is an interface that has id and name

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

  constructor(private http: HttpClient) { }

  public fetchOrganizations(): Observable<Organization[]> {
    return this.http.get<Organization[]>('https://beacon-network.org/api/organizations');
  }

  public fetchBeacons(): Observable<Beacons[]> {
    return this.http.get<Beacons[]>('https://beacon-network.org/api/beacons');
  
}

This is my component.html

<table mat-table [dataSource]="organizations$"
       >

  <ng-container matColumnDef="id">
    <th mat-header-cell *matHeaderCellDef>ID</th>
    <td mat-cell *matCellDef="let element"> {{element.id}} </td>
  </ng-container>

  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef>Name</th>
    <td mat-cell *matCellDef="let element"> {{element.name}} </td>
  </ng-container>

  <ng-container matColumnDef="beacons">
    <th mat-header-cell *matHeaderCellDef>Beacons</th>
    <td mat-cell *matCellDef="let element"> {{beaconCount}} </td>
  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

This gives me a table of ID, Name and Beacons. ID and Name are matched correctly. My problem is that beacons(beacon count) should have different numbers with the right match of the company name, I checked this with Postman and as an example Wellcome Trust Sanger Institute should return 5. According to what name I get I get 1, 2, 5 or 0 for all. Some outputs should be 21, 5, 4 etc.

Finally this is my component.ts:

import {Component, OnInit} from '@angular/core';
import {Observable, Subscription} from 'rxjs';
import {BeaconService} from './beacon.service';
import {Organization} from './organization';

@Component({
  selector: 'app-beacon',
  templateUrl: './beacon.component.html',
  styleUrls: ['./beacon.component.css']
})
export class BeaconComponent implements OnInit {

  organizations$: Observable<Organization[]>;
  beacon: any = {};
  displayedColumns = ['id', 'name', 'beacons'];

  organizations: Array<any>;

  organizationId: string;
  organizationName: string;
  beaconData: any = {};
  beacons: Array<any>;

  beaconCount = 0;
  organizationNameArray: Array<any> = [];


  constructor(private beaconService: BeaconService) {
    this.organizations$ = this.beaconService.fetchOrganizations();
  }

  ngOnInit() {

    this.beaconService.fetchOrganizations().subscribe((organizationData) => {
      this.organizations = organizationData;
      for (let i = 0; i < this.organizations.length; i  ) {
        this.organizationId = this.organizations[i].id;
        this.organizationName = this.organizations[i].name;
        this.organizationNameArray.push(this.organizationName);
      }
      return this.organizationNameArray;
    });

    this.beaconService.fetchBeacons().subscribe(beacons => {
      let organizationNameInBeacon;
      this.beacons = beacons;
      for (const beacon of this.beacons) {
        this.beaconCount = 0;
        for (const org of this.organizations) {
          if (beacon.organization === org.name) {
            organizationNameInBeacon = beacon.organization;
            this.beaconCount  ;
          }
        }
      }
      return this.beaconCount;
    });
  }
}

My output should be the name of the organization and the right beacon count for that. I need help here.

Response summary should be something like: Found: 6, Not Found: 39, Not Applicable:36

CodePudding user response:

I would just fork join the to response and then match them together and just use that observable for binding.

export class BeaconComponent implements OnInit {
  displayedColumns = ['id', 'name', 'beacons'];
  fetching:boolean
  countedBeaconOrgs$: Observable<OrganizationBecons[]>;
  constructor(private beaconService: BeaconService) {}

  ngOnInit() {
    this.fetching = true;
    this.countedBeaconOrgs$ = forkJoin([
      this.beaconService.fetchOrganizations(),
      this.beaconService.fetchBeacons(),
    ]).pipe(
      map(([orgs, beacons]): OrganizationBecons[] => {
        const countedOrgs: OrganizationBecons[] = [];
        for (const org of orgs) {
          countedOrgs.push({
            ...org,
            beaconCount: beacons.filter((b) => b.organization == org.name)
              .length,
          });
        }
        return countedOrgs;
      }),
      tap(()=> {
          this.fetching=false;
      })
    );

  }
}
export interface OrganizationBecons extends Organization {
  beaconCount: number;
}

the binding

<table mat-table [dataSource]="countedBeaconOrgs$" >
  <ng-container matColumnDef="id">
    <th mat-header-cell *matHeaderCellDef>ID</th>
    <td mat-cell *matCellDef="let element">{{ element.id }}    </td>
  </ng-container>

  <ng-container matColumnDef="name">
    <th mat-header-cell *matHeaderCellDef>Name</th>
    <td mat-cell *matCellDef="let element">{{ element.name }}</td>
  </ng-container>

  <ng-container matColumnDef="beacons">
    <th mat-header-cell *matHeaderCellDef>Beacon Count</th>
    <td mat-cell *matCellDef="let element">{{ element.beaconCount }}</td>
  </ng-container>
 <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
 <tr mat-row *matRowDef="let row; columns: displayedColumns"></tr>
</table>
<h1 *ngIf="fetching">Loading</h1>

updated stackblitz: https://stackblitz.com/edit/angular-vjttsn?file=src/beacon/beacon.component.ts

edit: Added ugly loading to the requests.

  • Related