How can we combine two phone calls and display the outcomes using typeahead ngx-bootstrap?

Let me walk you through the code that is currently working:

<input [formControl]="search" 
       [typeahead]="suggestions" 
       typeaheadOptionField="name"   
       (typeaheadOnSelect)="onSelectedDriver($event)">


ngOnInit(){
  public autocompleteValue() {
    this.search.valueChanges.subscribe(
      (selectedValue) => {
        this.searchVal(selectedValue)
      }
    );
  }
}


  public searchVal(val: string) {
    this.suggestions = (new Observable((observer: Observer<string>) => {
      observer.next(val);
    })).pipe(
      switchMap((query: string) => {
        if (query) {
          switch (this.serverApi) {
            case 'Driver':
              return this.getAllDrivers(query); 

            default:
              break;
          }
        }
        return of([]);
      })
    );
  }

In addition to this, here is another section of code:

  getAllDrivers(query: string) {
    return this.accountsService.getDrivers(query)
      .pipe(
        map((data: any) => {
          data.body?.forEach((driver: IDriver) => {
            driver.name = `${driver.firstName} ${driver.lastName}`
          });
          return data.body || [];
        }),
        tap(() => noop, err => {
          this.errorMessage = err && err.message || 'Something goes wrong';
        })
      )
  }

The current functionality is successful.

However, there is a need to extend the functionality further.

There is a requirement to merge two API calls into one and retrieve the combined result.

I attempted to do so without using typeahead with forkJoin..

   this.search.valueChanges.subscribe(val => { 
      let driverLoad = this.service.searchDrivers(val, [{ name: 'name', value: val }]);
      let affiliateLoad = this.service.searchAffiliates(val, [{ name: 'name', value: val }]) 
      forkJoin([driverLoad, affiliateLoad, travelAgenciesLoad]).subscribe(resultsOfSearch => {
        let driverArr = resultsOfSearch[0].body;
        let affiliateArr = resultsOfSearch[1].body; 
        this.autoCompleteResults = [...driverArr as [], ...affiliateArr as []];
        return this.autoCompleteResults
      })
    });

I am struggling to make this new piece of functionality work.

How can I effectively combine these operations and get the desired output?

Answer №1

forkJoin vs combineLatest

When choosing between forkJoin and combineLatest, it's important to consider how you want your observables to behave. ForkJoin will only emit a value when all source observables have completed, which may not be suitable for every situation.

Learn more about forkJoin here:

ForkJoin waits for Observables to complete and then combines the last values they emitted; it completes immediately if an empty array is passed.

On the other hand, if your three observables are continuous data streams that need to be combined before completion, combineLatest might be a better operator:

Read about combineLatest here

With combineLatest, whenever any input Observable emits a value, it computes a formula using the latest values from all inputs and emits the output of that formula.

//Define observables before subscribing to valueChanges
let driverLoad = this.service.searchDrivers(val, [{ name: 'name', value: val }]);
let affiliateLoad = this.service.searchAffiliates(val, [{ name: 'name', value: val }]) 
let combinationObservable$: Observable<any>;

// Subscribe to valueChanges to find the latest emitted value from driverLoad,
// affiliateLoad, and travelAgenciesLoad
this.search.valueChanges.subscribe(val => {
  combinationObservable$ = combineLatest([driverLoad, affiliateLoad, travelAgenciesLoad]); 
}

// Subscribe to combination Observable outside of the valueChanges subscription
combinationObservable$.subscribe(value => {
  console.log(value);
  this.autoCompleteResults = value;
});

Check out this StackBlitz example I created to simulate your observables using combineLatest.

Answer №2

Utilizing rxjs zip allows you to combine observables and emit their values as an array, providing the result directly in an array format.

import { zip } from 'rxjs';
let driverLoad = this.service.searchDrivers(val, [{ name: 'name', value: val }]).pipe(map(data => data.body));
let affiliateLoad = this.service.searchAffiliates(val, [{ name: 'name', value: val }]).pipe(map(data => data.body)) 

zip(driverLoad , affiliateLoad).subscribe((results: any[]) => console.log(results) )

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is preventing the spread type from being applied to `Record` in TypeScript?

export type AddResourceProps<K extends string, T extends any> = (resource: BasicResource) => Record<K, T> const addtionalResourse = addResourceProps ? addResourceProps(resource) : {} as Record<K,T> const result = { ...addtionalRe ...

Error: the attempt to execute the mongoose connection function has failed due to it not being recognized as a valid function

Hey there, I'm encountering the error TypeError: mongoose__WEBPACK_IMPORTED_MODULE_15___default.a.connect is not a function import mongoose from "mongoose"; const dbURI = 'myurlstuffhere'; mongoose.connect(dbURI , {useNewUrlParser: ...

"Sequencing http.get requests in Angular 2 using

In my service, I have a series of http.get requests structured as follows: constructor(private http:Http) {} getDetails(sysID:string){ var details; this.http.get('https://blahURL').map(res => res.json().filter(f => f.id == another.id)[0] ...

Underwhelming scroll speed when working with 9 columns in react-virtualized

I am currently utilizing react-virtualized in conjunction with material-ui table cells to establish a table featuring virtual scrolling. Although everything appears to be functioning correctly, I am experiencing intermittent performance slowdowns when navi ...

hide elements only when there is no string to display in Angular2/Typescript

As I experiment with my javascript/typescript code, I've encountered an issue where a string is displayed letter by letter perfectly fine. However, once the entire string is shown, the element containing it disappears and allows the bottom element to ...

Updating a boolean value when the checkbox is selected

Hey there! I'm currently working on a project using Angular and have a collection of elements that can be checked, which you can check out here. In terms of my business logic: stateChange(event: any, illRecipe: Attendance){ var state: State = { ...

What is the best way to subscribe to both the URL and parameters in the ActivatedRoute?

When the url changes, <code>activatedRoute.url.subscribe provides a list of urlsegments. Additionally, activatedRoute.queryParams.subscribe delivers an object of queryParams when they change. Is there a way to subscribe to both simultaneously in ord ...

Exploring the capabilities of TypeScript in conjunction with the useRoute function on React Navigation version

When using useRoute, I am attempting to extract the parameters like this: const route = useRoute(); const { params } = route; const { id, name, } = params; Although everything is functioning correctly, the linter is pointing out that id and na ...

The return value depends on the type of function argument passed

I am currently developing a type-safe JSON:API specification parser for handling API responses that can either contain a single object or an array of objects (). For example, when making a request like GET /article: { data: { type: 'article&ap ...

How can I link dropdown values to the corresponding property values within a nested array in Angular?

Within my JSON array, there are multiple similar items. Here is an example of one item: { "ownerID": "rkjgAs40NEuSJfp4jquNYQ", "defaultPriceScheduleID": null, "autoForward": false, "id": "44685 ...

Troubleshooting TypeScript when importing external JavaScript: Module not found or no type declaration file available

I recently acquired a VueJS admin template built in JS and am looking to integrate it into my existing TS application. However, when I attempt to transfer the components, views, and other elements, I encounter the following error message. Is there a way to ...

The default values for CSS filters

I have a keen interest in various CSS filters: blur brightness contrast grayscale hue-rotate invert opacity saturate sepia Could someone provide the default values for each filter (preferably as a % value, where applicable)? The MDN documentation does no ...

Encountering a 404 error while trying to deploy a React app on Verc

After deploying my React project with TypeScript using Vite, everything is working smoothly. However, I am encountering a 404 error when trying to refresh the page. Error: 404 NOT_FOUND Error Code: NOT_FOUND ...

Exploring Variables in Angular 11 HTML: A Guide to Debugging

The challenge In my Angular 11 web app, I am trying to troubleshoot and inspect the variables within the HTML code. While I have managed to retrieve the ctx.ngForOf variable, I feel like there is something missing in my process that I can't quite pi ...

Using Vue in conjunction with TypeScript and CSS modules

I am facing an issue with my SFC (single file vue component) that utilizes TypeScript, render functions, and CSS modules. <script lang="ts"> import Vue from 'vue'; export default Vue.extend({ props: { mode: { type: String, ...

What is the process for running Protractor in a project that is not using AngularCLI?

I am new to using Protractor and I am eager to run my first test. However, I am facing some difficulties on how to get started. I initially tried entering ng e2e in the cmd prompt but received a message stating that I "have to be inside an Angular CLI proj ...

An issue has arisen with loading chunks in Ionic 5/Angular, possibly due to an un

I am currently working on enhancing the offline capabilities of my Ionic 5 app. To achieve this, I have implemented a strategy where data is stored in SQLite while the app is connected, and then retrieved from SQLite when offline instead of making HTTP req ...

Retrieve information from an XML document

I have some XML content that looks like this: <Artificial name="Artifical name"> <Machine> <MachineEnvironment uri="environment" /> </Machine> <Mobile>taken phone, test when r1 100m ...

The @Hostlistener method consistently returns an 'undefined' value when passing in the @Input() value

I'm encountering an issue where the value from @Input() is undefined in my @Hostlistener method. What could be causing this? export class InputHelpComponent implements OnInit { isOpened: boolean = false; @Input() field!: string; @HostListener(& ...

The utilization of TypeScript featuring a variable that goes by two different names

As I dive into TypeScript code, coming from a Java background, I struggle to grasp the syntax used in this particular example. The snippet of code in question is extracted from the initial Material UI Select sample: const [labelWidth, setLabelWidth] = Rea ...