Angular 12's BehaviorSubject should have been empty object array, but it unexpectedly returns undefined

Exploring different scenarios with a livesearch functionality:

  • No user input (observable = undefined)
  • No results found (observable = empty array)
  • Results found (observable = non-empty array)

The issue lies in how my behavior subject interprets an empty array as "undefined".



  loc$ = new BehaviorSubject<SearchResult[] | undefined>(undefined);
  searchLocation$ = new BehaviorSubject<string>("");

  initModule(): void {
    this.searchLocation$.pipe(
      switchMap((searchTerm: string) => this.fetchLocation(searchTerm)),
    ).subscribe(locations => {
      console.log(locations); //returns undefined for an empty array `of([])` ;((
      this.loc$.next(locations);
    });

  }

  searchLocation(incSearchTerm: string): void {
    this.searchLocation$.next(incSearchTerm);
  }

  fetchLocation(incSearchTerm: string): Observable<SearchResult[] | undefined> {
    if (!incSearchTerm) {
      // return undefined when there's no search term
      return of(undefined);
    }

    return this.httpHandler.getLocations(incSearchTerm).pipe(
      tap(searchResults => {
        if (searchResults ) {
          return searchResults ;
        } else {
          // attempting to return an empty array, however it is interpreted as undefined
          return of([]);
        }
      })
    );
  }


Whenever I use of([]) hoping to get back an empty array, it always returns "undefined".

How can I address this issue by either:

  • Recognizing of([]) as an empty array
  • Returning a different observable that contains an empty array
  • Or approaching the three scenarios differently.

Thank you

Answer №1

If you want to retrieve values from getLocations, it's better to use the map operator instead of tap. The map operator transforms the emitted value, while tap is used for side effects. You can also simplify your code by using the nullish coalescing operator (??) instead of an if statement.

fetchLocation(incSearchTerm: string): Observable<SearchResult[] | undefined> {
  if (!incSearchTerm) {
    return of(undefined);
  }
  return this.httpHandler.getLocations(incSearchTerm).pipe(
    map(searchResults => searchResults ?? [])
  );
}

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

Is it possible for me to tap into the component creation process within the Angular Router?

Inspiration struck me when I realized the potential of adding a directive to the component designed for this particular route. It would elevate the functionality by letting me convey crucial information in a more declarative manner. Despite learning that ...

Troubleshooting issue with getServerSideProps not functioning in Next.js while utilizing Next-redux-wrapper and TypeScript

When attempting to trigger an action as outlined in the documentation using the getServerSideProps function with the help of next-redux-wrapper store and redux-thunk, I am encountering the following TypeScript error: ts(2322): Type '({ req }: GetServe ...

Leveraging the Power of JavaScript within Angular 12

Currently, I am in the process of learning how to utilize Angular 12 and am attempting to create a sidenav. While I am aware that I can use angular material for this task, I would prefer not to incorporate the associated CSS. My goal is to integrate this ...

Angular 13 does not currently have support for the experimental syntax 'importMeta' activated

Since upgrading to angular 13, I've encountered an issue while attempting to create a worker in the following manner: new Worker(new URL('../path/to/worker', import.meta.url), {type: 'module'}) This code works as expected with "ng ...

The parameter type (key: string, id: string, pagination: number) in the argument does not match the expected type of Boolean for the parameter

I'm facing an issue while trying to implement the following documentation: https://swr.vercel.app/ using my own setup: import React, { useEffect } from 'react' import PatientsTable from 'components/patients/PatientsTable' import ...

Using string interpolation within the innerHTML property in Angular 2

How do I render an expression using the [innerHTML] directive? public stringInterpolation: string = 'title'; public data: any = '<a>{{stringInterpolation}}</a>'; <div [innerHTML]="data"></div> The issue is th ...

Storing and sharing information between routes in Angular 2: The ultimate guide

As I launch my angular app, I make a request to an endpoint during initialization to retrieve data for specific routes. When I navigate to the home page, I fetch the home page data from the database and return it. Similarly, when I go to the contact route, ...

Unexpected behavior with Angular 10 behavior subject - encountering null value after invoking .next(value) function

Can anyone help me solve the mystery of why my user value turns null after I log in? This is the login page where an API is called and the result is obtained as shown below: https://i.stack.imgur.com/kDjSy.png Here is the authentication service implemen ...

Jasmine: utilizing unit test to spy on the invocation of a nested function

When running unit tests for an Angular app, I need to spy on a function called func1 to check if it is being called. However, within func1 there is a call to func2 and I also want to spy on that to see if it is being called. How should I structure my unit ...

The new data is not being fetched before *ngFor is updating

In the process of developing a "Meeting List" feature that allows users to create new meetings and join existing ones. My technology stack includes: FrontEnd: Angular API: Firebase Cloud Functions DB: Firebase realtime DB To display the list of meeting ...

Customize the element of the root node of a MUI component using the styled()

I am trying to implement the "component" prop with a MUI component (such as ListItem) using the styled() API. However, I am facing an issue where it says that "component" is not a valid prop. Can someone guide me on how to correctly achieve this? I have se ...

Creating Separate User and Admin Navigation in Angular: Step-by-Step Guide

I am facing an issue in my Angular project where I want to segregate the admin and user navigation similar to that of an e-commerce website. However, the children route is not functioning properly for the dashboard or user sections. Whenever I click on the ...

What is the best way to integrate my Angular keycloak setup with an idphint attribute?

I have successfully integrated the angular keycloak adapter from https://www.npmjs.com/package/keycloak-angular to connect with our keycloak server. Currently, I am exploring the idphint attribute to redirect the request to a different identity provider. ...

Validating specific controls in an Angular 2 FormGroup and marking them as invalid

Currently, I have implemented an Angular 2 Reactive form using FormGroup. The main requirement is to compare the values of two fields, for which I have included a validator in the FormGroup during creation. The validation process seems to be working effect ...

Creating a distinct input for each row in a table using Angular 2

I am encountering an issue with inputs being created for each row in my PrimeNG/datatable. The problem arises from the local variable #itsmIncident, which causes confusion when trying to pass values to the "Save" button as there are multiple rows involve ...

What is the syntax for declaring a boolean or object type?

Is it possible to create a variable in TypeScript that can hold either true/false or an object of booleans? I'm still learning TS and would like some input on this syntax. variableA: { a: boolean, b: boolean } | boolean I found a workaround for now, ...

Toggle visibility of an Angular 4 component based on the current route

Hello there, I'm facing an issue and not sure if it's possible to resolve. Essentially, I am looking to display a component only when the route matches a certain condition, and hide another component when the route matches a different condition. ...

Exploring the Power of TailwindCss in Storybook 6 for Angular Development

I am in the process of creating a component library using Angular version 11.2.8, and I'm attempting to integrate TailwindCss and Storybook 6. Despite trying various configurations, none seem to be working correctly for me. Whenever I run Storybook, ...

Tips for properly utilizing GeolocationPosition in TypeScript

Our goal is to utilize the Geolocation API to access the user's location. This particular code snippet appears to be functioning well: if (navigator.geolocation) { navigator.geolocation.getCurrentPosition((position: GeolocationPosition) => conso ...

Structuring a TypeScript microservices repository on GitHub: Best practices to follow

Currently, I am in the process of designing a set of microservices. The structure I have been following involves each item having its own repository. my-project-logger my-project-numbers-service includes: my-project-logger type definitions + class obje ...