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

Encountering Build Issue: "NgSemanticModule is not recognized as an NgModule" persists despite inclusion of dependencies and importing into primary module

I have posted my module, component, and package file here. I am attempting to implement a click event with ngif, but I keep encountering an error. The specific error message is "ERROR in NgSemanticModule is not an NgModule". I'm unsure if this error ...

Error encountered while running npm build: Typescript issue within plotly.js/index.d.ts

Trying to implement this code snippet: import createPlotlyComponent from 'react-plotly.js/factory'; const Plot = createPlotlyComponent(window.Plotly); in my React project implemented in TypeScript. Encountered a TypeScript error during npm run ...

Throttle the asynchronous function to guarantee sequential execution

Is it possible to use lodash in a way that debounces an async function so it runs after a specified delay and only after the latest fired async function has finished? Consider this example: import _ from "lodash" const debouncedFunc = _.debounc ...

What is the best way to search for an Enum based on its value?

One of my challenges involves an enum containing various API messages that I have already translated for display in the front-end: export enum API_MESSAGES { FAILED_TO_LOAD = 'Failed to load data', TOKEN_INVALID = 'Token seems to be inva ...

How can I use Angular 4 typescript to deactivate a button based on the value of a boolean variable?

I am looking to define a function in TypeScript called 'isActive()', which I will then invoke on a button within my HTML file. Additionally, I have already declared a boolean variable named 'isActive'. In this scenario, I have two butto ...

Invoke cloud functions independently of waiting for a response

Attempting a clever workaround with cloud functions, but struggling to pinpoint the problem. Currently utilizing now.sh for hosting serverless functions and aiming to invoke one function from another. Let's assume there are two functions defined, fet ...

What is the best way to integrate ng-bootstrap into an nx mono repository?

Encountering an issue when attempting to install ng-bootstrap in a multi-project mono repo using Nx. The error message received is as follows: npx ng add @ng-bootstrap/ng-bootstrap --project=web-app The add command needs to be executed in an Angular proje ...

Can TSLint and ESLint give a warning when a function is accessed as a property?

There have been instances where I've made this specific mistake, and I'm curious if there are any ESLint or TSLint rules in place that could detect it. if (this.isBrowser && this.imageURL) {.....} private isBrowser(): boolean{ retur ...

What is the process for invoking instance methods dynamically in TypeScript?

There is an object in my possession and the goal is to dynamically invoke a method on it. It would be ideal to have typechecking, although that may prove to be unattainable. Unfortunately, the current situation is that I cannot even get it to compile: ...

Having trouble accessing functions in Typescript when importing JavaScript files, although able to access them in HTML

Recently, I started incorporating TypeScript and React into my company's existing JavaScript code base. It has been a bit of a rollercoaster ride, as I'm sure many can relate to. After conquering major obstacles such as setting up webpack correc ...

What is the reason for the manual update of a view when copying an object's attributes into another object, as opposed to using Object.assign()?

In my application, I have a parent component called 'EmployeeComponent' that is responsible for displaying a list of employees. Additionally, there is a child component named 'EmployeeDetailComponent' which displays the details of the s ...

Disable TS4023 error in TypeScript: Unable to name external module "xyz"

//custom-slice.js import { createCustomSlice } from '@my/data-toolkit'; /* ***********************For Managing all the divisions data****************************** */ export const divisionDataSlice = createCustomSlice({ name: 'divisionda ...

AG-Grid: Enhancing Cell Interactivity

Within ag-grid, there is a feature called stopEditingWhenGridLosesFocus. I recently developed my own custom cell editor using a cell editor component. I am curious to know if there exists a similar property or method to achieve the behavior of stopEditing ...

The error message "Property 'then' is not available on type 'void' within Ionic 2" is displayed

When retrieving data from the Google API within the function of the details.ts file, I have set up a service as shown below. However, I am encountering a Typescript error stating Property 'then' does not exist on type 'void'. this.type ...

The program is requesting an expression involving the user's username

https://i.stack.imgur.com/tf1QD.png What is causing the issue with trying to use user.username? as an expression? While user.username returns a string of the User's username, I am unable to index it into listOfPlayers[]. client.on("messageReacti ...

Is there a way to retrieve a data type from a class in TypeScript?

Within my code, there exists a class: class Person { name: string; age: number; gender: string; constructor(params: any){ this.name = params.name; this.age = params.age; this.gender = params.gender; } } My question is how ca ...

How to link a selection choice to an option using Angular 13

Can anyone provide guidance on how to bind data with a select option in Angular? I've tried multiple approaches but haven't been successful in getting the data to display in the options. Any assistance would be greatly appreciated. Thank you in a ...

Eliminate incorrect or invalid state when resetting a dropdown in an Angular ng-select component

I have integrated the ng-select plugin into my Angular project for handling dropdowns. One specific requirement I have is to reset the second dropdown when the first dropdown is changed. Below is a snippet of the code: <ng-select [items]="branchMo ...

Is it possible to implement lazy loading for data in TypeScript classes?

Looking to optimize my Angular application's data structure when consuming a RESTful API. My goal is to only load necessary data from the server on demand. For instance, if I have a collection of Building objects each with a set of tenant IDs in an a ...

The Angular frontend application with proxy configuration is sending requests to the incorrect backend URL

My application is using Angular 11.0.6 as the front end, deployed on IIS and configured for mywebsite.com (port 80). The backend consists of a dotnet core web API deployed on IIS and configured for my.server.ip.address:190. Both the front end and back end ...