What is the secret to getting this nested observable to function correctly?

Currently, I am working on an autocomplete feature that dynamically filters a list of meals based on the user's input:

export class MealAutocompleteComponent {

  mealCtrl = new FormControl()
  filteredMeals: Observable<Array<Meal>>
  liveMeals$: Observable<Array<Meal>>
  mealsSnapshot: Meal[]

  constructor(private mealsQuery: MealsQuery) {
    this.liveMeals$ = this.mealsQuery.all$        // <= observable (not used)
    this.mealsSnapshot= this.mealsQuery.getAll()  // <= array (used)

    // Observing user input and triggering filtering process
    this.filteredMeals = this.mealCtrl.valueChanges.pipe(
      startWith(null),
      map((filterTerm: string | null) => {
        let mealArr: Array<Meal> = mealsQuery.getAll() // <= Using observable instead
        return filterTerm ? this._filter(filterTerm, mealArr) : mealArr
      })
    )
  }

  private _filter(value: string, meals:Array<Meal>): Array<Meal> {
    // Filtering method for meals
    const filterValue = value.toLowerCase()

    return meals.filter(meal =>
      meal.label.toLowerCase().indexOf(filterValue) === 0
    )
  }

}

What is the correct approach to transition from using meals:Array to meals:Observable?

The current code functions as intended. However, there are two sources to retrieve the complete list of meals - an array this.mealsSnapshot and an observable: this.liveMeals.

In the provided code snippet, the mealsSnapshot array is utilized. But ideally, I would like to leverage the flexibility offered by the liveMeals$ observable, derived from a state store. Unfortunately, I am unsure about the appropriate RxJS operators required for this transition. The liveMeals$ observable returns a singular array of meals.

I attempted the following implementation but encountered issues with nested subscriptions which go against reactive programming guidelines, resulting in inefficient and messy code.

    this.filteredMeals = this.mealCtrl.valueChanges.pipe(
      startWith(null),
      concatMap((filterTerm: string | null) => {
        this.liveMeals$.pipe(
          first()  
        ).subscribe((mealsArr:Meal) => {
          return filterTerm ? this._filter(filterTerm, mealsArr) : mealsArr
        }
        )
      })
    )

Could you provide insights into effectively utilizing

liveMeals$:Observable<Array>
instead of relying on mealsSnapshot?

Answer №1

Opting for a higher order operator like concatMap is the right choice when transitioning from one observable to another. However, the subscription inside is not necessary. Instead of subscribing, you can switch to a different observable and utilize the map operator based on your condition.

In scenarios such as typeaheads, consider incorporating the debounceTime operator to regulate the emissions that trigger the filter.

Give this a try:

this.filteredMeals = this.mealCtrl.valueChanges.pipe(
  startWith(null),
  debounceTime(300),                
  concatMap((filterTerm: string | null) =>
    this.mealsQuery.all$.pipe(
      take(1),                      
      map(meal => filterTerm ? this._filter(filterTerm, meal) : meal)
    );
  )
);

Distinguishing between first() and take(1):

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

Adding a new line in the configurations of MatDialogConfig (Angular)

Here is a code snippet: private mDialog: MatDialog, const dialog = new MatDialogConfig(); msg = "I enjoy coding in Angular.\r\n I am learning TypeScript." dialog.data = { message:msg }; alert (msg); mDialog.open(AB ...

Why is it that when I try to create a table using the "Create Table" statement, I keep getting an error saying "Near '(': syntax error"?

Error : There seems to be a syntax error near "(". Here is the SQL statement causing the issue: CREATE TABLE IF NOT EXISTS tickets ( numero INTEGER PRIMARY KEY AUTOINCREMENT, identifier VARCHAR(4) NOT NULL, subject VARCHAR(150) NOT NULL, ...

Utilizing a Custom Validator to Compare Two Values in a Dynamic FormArray in Angular 7

Within the "additionalForm" group, there is a formArray named "validations" that dynamically binds values to the validtionsField array. The validtionsField array contains three objects with two values that need to be compared: Min-length and Max-Length. F ...

checkbox with an option tag

I need help with implementing multi-select checkboxes inside an Angular 4 application. The checkboxes are not appearing next to the team names as intended. Can anyone assist me with this issue? Below is a snippet of my HTML code: <select class="form-c ...

"Learn how to include date parameters in the URL query string using Node.js and Express, and discover how to efficiently parse

Currently, I am working on an Angular 2 app that has a service responsible for sending HTTP requests to retrieve data from an Oracle DB using the node-oracle db and Express framework. I have successfully created REST APIs using Express; however, I now ne ...

Experiencing a problem with updating records in angular?

angular version: Angular CLI: 9.0.0-rc.7 I have encountered an issue while trying to update a record. After clicking on the edit icon, I am able to make changes to the record in the form. However, when I click on the Edit Button, the record gets updated i ...

I am struggling to understand the significance of the $ symbol in this particular context

I came across the following snippet in a book I've been reading: `images/${Date.now()}.jpg` The curly brackets used here signify 'out of string', but I'm unsure about the meaning of $... P.S. Honestly, I didn't want to ask a que ...

What is the method to define a loosely typed object literal in a TypeScript declaration?

We are currently in the process of creating TypeScript definitions for a library called args-js, which is designed to parse query strings and provide the results in an object literal format. For example: ?name=miriam&age=26 This input will produce th ...

Unable to locate the module styled-components/native in React Native

When adding types in tsconfig.json to remove TypeScript complaints and enable navigation to a package, the code looks like this: import styled, {ThemeProvider} from 'styled-components/native'; The package needed is: @types/styled-components-re ...

What prevents ts-morph from retrieving the classes within a TypeScript project?

Utilizing ts-morph, I am examining the inheritance relationships of classes in a project: For testing purposes, I have downloaded an open-source projectantv/x6: import { Project } from "ts-morph"; const project = new Project(); project.addDire ...

Tips for preventing the rxjs error "TypeError: Cannot read properties of undefined" in the Angular framework

When I try to open the page in Angular, I encounter this error: core.mjs:6485 ERROR TypeError: Cannot read properties of undefined (reading 'getDocumentContent') In my Angular component, I have an observable like this: selectedDocument$ = this.s ...

Locate the nearest upcoming date and time to today's date in the JSON response

I am currently working with an API that provides a response containing the `start_time` field in JSON format. My goal is to extract the ID from the JSON object whose next date time is closest to the current date and time, excluding any dates from the past. ...

TS2531: Potentially null object

I am facing an issue in my React-TypeScript project with the following code snippet. Despite having null checks, I am still getting an error "object is possibly null" while running the app. The error specifically occurs in the last part of the if conditio ...

Choose a Spot on the Open Layers map using a marker or icon

As a beginner in the world of Open Layers, I'm eager to learn how to utilize markers or icons to obtain user location. Additionally, I hope to harness the power of Angular to extract these location details. ...

Having trouble with Angular 2 not properly sending POST requests?

Having some trouble with a POST request using Angular 2 HTTP? Check out the code snippet below: import { Injectable } from '@angular/core'; import { Http, Response, Headers, RequestOptions } from '@angular/http'; import 'rxjs/add ...

Warning: Installing packages with names containing "esbuild-" using npm may

After upgrading my Angular version from 10 to 12 using the steps provided at https://update.angular.io/?l=3&v=10.0-12.0, I successfully completed every step. However, upon running npm install, I encountered the following warnings: npm WARN optional SKI ...

What is the process for selectively adding interceptors to app.module?

After searching through various topics, I have not found a solution that addresses my specific issue. To provide some context, we have an Angular App that operates in two modes - one mode uses one API while the other mode utilizes a different API. My goal ...

Tips for retrieving additional values from a chosen variable in Angular 10

Here is an array I have: export const Glcode = [ { id: 1, Type: 'Asset', Name: 'Cash at Head Office', code: '10018' }, { id: 2, Type: 'Asset', Name: 'POS ACCOUNT ', code: '10432' }, { ...

Type-safe Immutable.js Records with TypeScript

I'm struggling to find a suitable solution for my query. I am aiming to define data types using an interface in TypeScript, but my data consists of Immutable.js records making it more complex. Please refer to the example provided below. interface tre ...

The JSX element 'SubscribeCard' does not contain any construct or call signatures

I'm looking to implement the react-subscribe-card module for handling email subscriptions in my react.js project. Below is the code snippet from my popup.tsx file: import React from "react"; import SubscribeCard from "react-subscribe-c ...