A single click is required for Observables to load on an HTML page

While working on my Angular web application, I encountered an issue with displaying data when using Observables and Subjects. Typically, when searching the Firebase DB, I use

*ngFor="let myvar of _myvar | async"
in my HTML to display the retrieved data. However, whenever a Subject comes into play, the data is not displayed until I interact with an element on the page.
Below is the code snippet where the problem occurs:

<section>
    <div id="paddingTop" fxLayout="row" fxLayout.lt-md="column" fxLayoutAlign="space-around center">
        <div>
          <h2>*****************</h2>
          <mat-icon>place</mat-icon>
          <mat-form-field color="accent" appearance="fill" id="searchAddress">
            <mat-label>*****************</mat-label>
            <input 
              matInput 
              ngx-google-places-autocomplete #placesRef="ngx-places" 
              (onAddressChange)="handleAddressChange($event)" />
            <button mat-button *ngIf="address" matSuffix mat-icon-button aria-label="Clear" (click)="address=''">
              <mat-icon>close</mat-icon>
            </button>
          </mat-form-field>
        </div>
    </div>
    <div id="searchPart">
        <h2>*****************</h2>
        <section class="mobile" fxLayout="column" fxLayoutAlign="center center" fxLayoutGap="20px" fxHide.lg *ngFor="let id of _feedersId | async">
          <app-feeder-card
            [feederId] = "id"
            [clientId] = "this.uid"
          ></app-feeder-card>
        </section>
        <section *ngIf="feedersId.length == 0" fxLayout="column" fxLayoutAlign="center center" >
          <p>*****************</p>
          <p>
            <mat-icon>arrow_upward</mat-icon>
            *****************
            <mat-icon>arrow_upward</mat-icon>
          </p>
        </section>
    </div>
</section>

home.component.ts

import { Component, OnInit } from '@angular/core';
import { AngularFirestore } from '@angular/fire/firestore';
import { Router } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { AuthService } from 'src/app/auth/auth.service';
import { Order } from 'src/app/order/order.model';
import { User } from '../user.model';

@Component({
  selector: 'app-user-home',
  templateUrl: './user-home.component.html',
  styleUrls: ['./user-home.component.scss']
})
export class UserHomeComponent implements OnInit {

  orders: Observable<Order[]>; 
  feedersId: Array<string> = [];
  _feedersId: Observable<Array<string>> = this.getFeederArray();
  uid: string;

  constructor(private router: Router, private authService: AuthService, private db: AngularFirestore) {}

  ngOnInit(): void {
    this.getFeederArray().subscribe(r => {
      console.log('tests')
      this.setFeederId(r);
    })
  }

  address = '';

  public handleAddressChange(address: any) {
    console.log(address);
    this.address = address.formatted_address;
    const lat = address.geometry.location.lat();
    const lng = address.geometry.location.lng();
    const adrs = address.formatted_address;

    this.router.navigate(['/search-feeder/', lat, lng, adrs]);
  }
  
  getUser(): Observable<User> {
    return this.authService.getUser().switchMap(user => {
      this.uid = user.uid;
      return this.db.collection('user').doc(user.uid).valueChanges({ idField: 'id' }) as Observable<User>;
    }).map(response => {
      return response;
    });
  }

  getFeederArray(): Observable<Array<string>> {
    let toReturn: Array<string> = [];
    var subject = new Subject<Array<string>>();
    this.getUser().subscribe(user => {
      this.orders = this.db.collection("orders", ref => {
        return ref
        .where("clientId", "==", user.id)
      }).valueChanges({ idField: 'id' }) as Observable<Order[]>;
      this.orders.subscribe(orders => {
        orders.forEach(order => {
          if(toReturn.indexOf(order.feederId) == -1) {
            toReturn.push(order.feederId);
          }
        })
      })
      subject.next(toReturn);
    })
    return subject.asObservable();
  }
  
  setFeederId(ids: Array<string>) {
    this.feedersId = ids;
  }
}

Answer №1

I have optimized the getFeederArray function by simplifying it to return a single observable without the need to subscribe to two observables within it.

Please review the changes made and test the updated code below:

  getFeederArray(): Observable<string[]> {
    return this.getUser().pipe(
      switchMap((user) => {
        this.orders = this.db
          .collection("orders", (ref) => ref.where("clientId", "==", user.id))
          .valueChanges({ idField: "id" }) as Observable<Order[]>;

        return this.orders;
      }),
      map((orders) => orders.map((order) => order.feederId))
    );
  }

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

How to dynamically assign a type based on a single choice from multiple options (props)

I have a props object that includes: { option1, option2, option3, option4, general, otherProps } The requirement is to allow only one option to be used at a time. Here are the types defined: interface MyTypes { option1: boolean option2: boolean option3 ...

What is the best way to insert a chart into a div using *ngIf in Angular?

I just started using chart.js and successfully created the desired chart. However, when attempting to implement two tab buttons - one for displaying tables and the other for showing the chart - using *ngIf command, I encountered an error: Chart.js:9369 F ...

Looking for recommendations on the best tools to use for starting an Angular 2 project?

After successfully creating an Angular 2 web app on my computer, I encountered a problem when trying to build it for production. Instead of using my project files, angular-cli generated a "Hello World" app. The confusion arose because I was initially using ...

Design a TypeScript interface inspired by a set static array

I am working with an array of predefined strings and I need to create an interface based on them. To illustrate, here is an example of pseudo-interfaces: const options = ["option1", "option2", "option3"]; interface Selection { choice: keyof options; ...

How can you check the status of a user in a Guild using Discord JS?

Is there a way to retrieve the online status of any user in a guild where the bot is present? Although I can currently access the online status of the message author, I would like to be able to retrieve the online status of any user by using the following ...

The feature of Nuxt 3's tsconfig path seems to be malfunctioning when accessed from the

Take a look at my file structure below -shared --foo.ts -web-ui (nuxt project) --pages --index.vue --index.ts --tsconfig.json This is the tsconfig for my nuxt setup. { // https://v3.nuxtjs.org/concepts/typescript "exte ...

one-time occurrence of $mdToast injection within a parent class

Seeking advice on how to efficiently place a single instance of $mdToast (from Angular Material) into a base class (Typescript). In my UI, I have five tabs with separate controller instances and it seemed logical to centralize the $mdToast declaration in a ...

Exploring the method to retrieve a dynamically added property in Typescript

My React Component Loader receives certain props. The contentAlign property is only available when the local property exists and its value is 'relative'. I am encountering an error when trying to include contentAlign in the props, and I cannot ...

Nativescript Image-picker is encountering difficulties locating files in external storage

I have been using nativescript-imagepicker from the related website and followed all the instructions in the documentation and sample codes. I even set the permission code in AndroidManifest.xml for API 29 and higher. However, I encountered an error after ...

Tips for preventing the newly updated value from being linked to another array within Angular 13

Currently, I am using angular13 and working on a functionality where there is a button to move items from the left side to the right side. Interestingly, when an item is moved from the left to the right side and then edited under the right side, the edited ...

Tips for enhancing the appearance of the dropdown scrollbar in PrimeNG

Just started exploring Angular and I've been struggling to customize the scrollbar on a PrimeNG dropdown. Does anyone have any tips or tricks to achieve this? Here is the HTML code: <p-autoComplete placeholder="- Select -" (onSelect)="onSelect(dh ...

How can I choose an option in a dropdown field labeled as ejs-dropdownlist with WebDriver in an Angular web application?

After spending some time grappling with this issue, I managed to find a solution. The ejs-dropdownlist tag is present on a web page that is currently in the development stage using Angular. Here is the complete XPath for the dropdown I am attempting to i ...

The Angular error message InvalidValueError is thrown when the Map function expects a mapDiv of type HTMLElement, but instead receives a

When attempting to initialize Google Maps, I encountered a particular problem. In this div, I am trying to load the map but consistently receiving the same error message. I attempted to use ngAfterViewInit() in case the view wasn't fully loaded befo ...

NextJS is currently unable to identify and interpret TypeScript files

I am looking to build my website using TypeScript instead of JavaScript. I followed the NextJS official guide for installing TS from scratch, but when I execute npm run dev, a 404 Error page greets me. Okay, below is my tsconfig.json: { "compilerOption ...

Exploring the power of Vue CLI service in conjunction with TypeScript

I've recently set up a Vue project using the Vue CLI, but now I am looking to incorporate TypeScript into it. While exploring options, I came across this helpful guide. However, it suggests adding a Webpack configuration and replacing vue-cli-service ...

Leveraging the `--max-http-header-size` flag with ts-node

Encountered an issue when trying to use ts-node with the --max-http-header-size 15000 flag. It works fine with regular node, but unfortunately, ts-node does not support that option ...

Failure in Dependency Injection in Angular with Typescript

My mobile application utilizes AngularJS for its structure and functionality. Below is the code snippet: /// <reference path="../Scripts/angular.d.ts" /> /// <reference path="testCtrl.ts" /> /// <reference path="testSvc.ts" /> angular.mo ...

Implementing a back button in an RTL layout with Ionic 2

Just starting an Ionic 2 app in Arabic language requires a RTL layout. I decided to go with the side menu template. Adding the following line for configuring the app to RTL perfectly changed everything's direction, except for the back button which st ...

How can Angular 2 e2e tests maintain respect for their execution order?

What's the best way to ensure that Angular 2 e2e tests run in the order they are declared? I am currently using Angular-cli for my project. ...

For Angular 4, simply add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of the component in order to permit any element

After using angular-cli to create a new project (ng new my-project-name), I ran npm run test successfully without any issues. To display font icons in my project, I added the Font Awesome module from https://www.npmjs.com/package/angular-font-awesome. In ...