Encountering difficulties with a custom Firestore service when attempting to extend it after updating to Angular 9

My custom class that wraps Angular Firestore is designed to be extended and used throughout my application. However, after updating to Angular 9, this setup no longer functions properly. For the complete code snippet, visit .

The abstract class wrapper:

import { Inject } from '@angular/core';
import { AngularFirestore, QueryFn } from '@angular/fire/firestore';
import { Observable } from 'rxjs';
import { tap } from 'rxjs/operators';
import { environment } from 'src/environments/environment';

export abstract class FirestoreService<T> {

    protected abstract basePath: string;

    constructor(
        @Inject(AngularFirestore) protected firestore: AngularFirestore,
    ) {

    }

     collection$(queryFn?: QueryFn): Observable<T[]> {
        return this.firestore.collection<T>(`${this.basePath}`, queryFn).valueChanges().pipe(
            tap(r => {
                if (!environment.production) {
                    console.groupCollapsed(`Firestore Streaming [${this.basePath}] [collection$]`);
                    console.table(r);
                    console.groupEnd();
                }
            }),
        );
    }
}

This class is then extended in:

import { Injectable } from '@angular/core';
import { FirestoreService } from 'src/app/core/services/firestore.service';
import { Employee } from '../models/employee';

@Injectable({
    providedIn: 'root'
})
export class EmployeeFirestore extends FirestoreService<Employee> {

    protected basePath: string = 'employees';

}

And injected in:

import { EmployeesPageStore } from './employees-page.store';
import { EmployeeFirestore } from './employee.firestore';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { Employee } from '../models/employee';
import { tap, map } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class EmployeesService {

  constructor(
    private firestore: EmployeeFirestore,
    private store: EmployeesPageStore
  ) {
    this.firestore.collection$().pipe(
      tap(employees => {
        this.store.patch({
          loading: false,
          employees,
          totalEmployees: employees.length,
          totalDrivers: employees.filter(employee => employee.hasDriverLicense).length,
          totalRosarioEmployees: employees.filter(employee => employee.location === 'Rosario').length,
        }, `employees collection subscription`);
      })
    ).subscribe();
  }

While this setup works fine in Angular 8, it throws an error (shown in developer tools) in Angular 9:

ERROR Error: Uncaught (in promise): TypeError: Cannot read property 'collection' of undefined
TypeError: Cannot read property 'collection' of undefined
    at EmployeeFirestore.collection$ (firestore.service.ts:30)
    at new EmployeesService (employees.service.ts:17)
    at Object.EmployeesService_Factory [as factory] (employees.service.ts:119)
    at R3Injector.hydrate (core.js:16765)
    at R3Injector.get (core.js:16526)
    at NgModuleRef$1.get (core.js:35567)
    at Object.get (core.js:33358)
    at getOrCreateInjectable (core.js:5470)
    at Module.ɵɵdirectiveInject (core.js:20777)
    at NodeInjectorFactory.EmployeesSummaryComponent_Factory [as factory] (employees-summary.component.ts:10)
    at resolvePromise (zone-evergreen.js:793)
    at resolvePromise (zone-evergreen.js:752)
    at zone-evergreen.js:854
    at ZoneDelegate.invokeTask (zone-evergreen.js:400)
    at Object.onInvokeTask (core.js:40772)
    at ZoneDelegate.invokeTask (zone-evergreen.js:399)
    at Zone.runTask (zone-evergreen.js:168)
    at drainMicroTaskQueue (zone-evergreen.js:570)
    at ZoneTask.invokeTask [as invoke] (zone-evergreen.js:485)
    at invokeTask (zone-evergreen.js:1596)

Answer №1

The issue arises from the abstract class not initializing the firestore in its constructor. While it may seem like a bug, adding the @Injectable() decorator to the abstract class can ensure that the firestore is properly initialized in the extended class.

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

Edit CSS attributes within Angular 2+ framework

When using jQuery, we have the ability to do the following: JQuery('.someStyle') .css({"background", "red"}) This allows us to directly change the CSS property in style. While working with Angular 2+, we can use [style.<property>] for ...

Using getter functions and Visual Studio for TypeScript

In my TypeScript classes in Visual Studio, I have been implementing getter functions. I find that using getter functions helps to clean up my code, although there is one issue that I would like to address. class Foo { doWork(){ console.log(this.bar ...

Setting a default value and object ID in Angular's reactive forms for a select dropdown

Having an issue with validating a default value in a selector that serves as a message to select an option. The problem arises from the validation of this option, as it is linked to the object ID of another collection in the database (mongoose-express js). ...

Can an Angular 9 application access an uploaded file through an HTTP request from the $_FILES array?

I'm currently facing an issue when attempting to send a file to a PHP server using an HTTP request in Angular 9. The problem lies in the fact that the server is not able to receive the uploaded file in $_FILES. Below is the code snippet I have written ...

Exploring the benefits of integrating Apache Thrift with TypeScript

After running the apache thrift compiler, I now have generated .js and .d.ts files. How do I incorporate these files into my current Angular2/Typescript project? I attempted to do so with the following lines of code: ///<reference path="./thrift.d.ts"/ ...

Error: Unhandled promise rejection: Trying to access a property of null (specifically 'branch') causing a TypeError

While developing a dashboard for an Angular application, I encountered an error when trying to access the dashboard: ERROR Error: Uncaught (in promise): TypeError: Cannot read properties of null (reading 'branch') TypeError: Cannot read propert ...

How can I test for equality with an array item using v-if in Vue.js?

Currently, I am facing a challenge in my Vue.js project where I need to determine if a number is equal to an element within an array. Here is the code snippet that I am working with: <div v-if="someValue != arrayElement"> // </div> I am st ...

The requested module cannot be located, were you referring to "js" instead?

I am currently developing a React application using webpack and typescript. I have integrated the dependency react-financial-charts into my project, and it is properly specified in the package.json. Inside the node_modules directory, there are two folders ...

How to retrieve a value from an Angular form control in an HTML file

I have a button that toggles between map view and list view <ion-content> <ion-segment #viewController (ionChange)="changeViewState($event)"> <ion-segment-button value="map"> <ion-label>Map</ion-label> & ...

Having trouble getting `npm start` to work for the Lite-server?

As a newcomer to Angular and web programming, I attempted to replicate the quickstart project on github/angular by using "npm start" to initiate lite-server. However, following a tutorial [link] (https://www.youtube.com/watch?v=-zW1zHqsdyc&t=804s), I ...

Getting the value from an Observable in Angular 2 after using the CanActivate guard and subscribing

I am using a "CanActivate" method in my web service to check if the user is logged in. The "CanActivate" method returns an Observable. My main concern is how to retrieve this boolean value so that I can adjust my view based on whether the user is connecte ...

An automatic conversion cannot handle spaces and prohibited characters in Object keys

The AlphaVantage API uses spaces and periods in the keys. Their API documentation is not formal, but you can find it in their demo URL. In my Typescript application, I have created data structures for this purpose (feel free to use them once we solve the ...

Angular TimeTracker for tracking time spent on tasks

I need help creating a timer that starts counting from 0. Unfortunately, when I click the button to start the timer, it doesn't count properly. Can anyone assist me in figuring out why? How can I format this timer to display hours:minutes:seconds li ...

Implementing dynamic progress bar updates in an Angular application using Bootstrap

Seeking to create a progress bar in a Word object for a language vocabulary training app, displaying the number of correct and wrong answers. <div class="progress"> <div class="progress-bar progress-bar-striped progress-bar-a ...

Detecting the presence of a session in Angular2 and nodejs using express

My server-side session creation is functioning properly, but I need to be able to hide certain elements in an Angular2 component template depending on whether the session exists. How can I check within my Angular2 component whether the server-created sessi ...

Converting JSONSchema into TypeScript: Creating a structure with key-value pairs of strings

I am working with json-schema-to-typescript and looking to define an array of strings. Currently, my code looks like this: "type": "object", "description": "...", "additionalProperties": true, "items": { "type": "string" ...

Tips for making use of incomplete types

Is there a way to reference a type in TypeScript without including all of its required fields, without creating a new interface or making all fields optional? Consider the following scenario: interface Test { one: string; two: string; } _.findWhe ...

How to choose a particular Excel spreadsheet in Angular before importing the file?

I am currently working on a new feature that allows users to choose a specific Excel worksheet from a dropdown list before importing a file. However, I am facing some difficulty in adding the worksheet names to the dropdown list. Right now, I have placehol ...

Updating a string's value in Angular based on user input

I am currently developing a custom offer letter template that will dynamically update key data points such as Name, Address, Role, Salary, etc based on the selected candidate from a list. The dynamic data points will be enclosed within <<>> in ...

Is there a way to update the parent state from a child component in React when using Switch Route?

I have a page that features a control panel for modifying the content on display through Switch-Route. The code structure is as follows: <div className="controls"> some controls here </div> <Switch> <Route exact path=&apo ...