I am struggling to delete real-time records in Angular using Firestore

I am facing an issue with my Angular code. I want to be able to delete a record and have it reflect in real-time. When I create a product, it works fine, but deleting the product doesn't work unless I refresh the browser. I'm not sure where the problem in the code might be.

My suspicion is that the issue lies in the getProducts(): Promise method. Whenever I click on Delete, it creates a new product, and the deletion only happens after I refresh the browser.

Your assistance would be greatly appreciated. Thank you.

My data.service.ts

import { Injectable } from '@angular/core';
import { Producto } from '../interfaces/producto';
import { AngularFirestore } from '@angular/fire/firestore';
import { NgxSpinnerService } from "ngx-spinner";
import Swal from 'sweetalert2';


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

  private colProduct: string = 'Products';
  private products: Producto[] = [];

  constructor(private _firestore: AngularFirestore, private _spinner: NgxSpinnerService) {

  }


  showSpinner(): void {
    this._spinner.show();
  }
  hideSpinner(): void {
    this._spinner.hide();
  }
  showAlert(icon: any, title: string, text: string, showConfirmButton: boolean, position: any, timer: number) {
    Swal.fire({
      icon: icon,
      title: title,
      text: text,
      showConfirmButton: showConfirmButton,
      position: position,
      timer: timer

    })
  }

  updateProduct(data: any, id: string) {

  }

  deleteProduct(id: string): Promise<any> {
    return this._firestore.collection(this.colProduct).doc(id).delete();
  }

  createProduct(producto: Producto): Promise<any> {
    return this._firestore.collection(this.colProduct).add(producto);
  }

  getProducts(): Promise<any> {
    return new Promise(resolve => {
      this._firestore.collection(this.colProduct).stateChanges().subscribe(collection => {
        collection.forEach((document) => {
          const data:any  = document.payload.doc.data();
          data.id = document.payload.doc.id;
          this.products.push(data);

        });


      resolve(this.products);


      });

    });
  }
}

my components.ts

    import { Component, OnInit } from '@angular/core';
import { Producto } from '../shared/interfaces/producto';
import { FormGroup, FormControl, Validators } from '@angular/forms';
import { DataService } from '../shared/services/data.service';

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

  public form: FormGroup;

  public productos: Producto[] = [];

  constructor(private _data: DataService) { }

  ngOnInit(): void {
    this._data.getProducts().then((data: Producto[]) => {
      this.productos = data;
    });
    this.form = new FormGroup({
      title: new FormControl('', Validators.required),
      pricing: new FormControl('', Validators.required),
      description: new FormControl('', Validators.required)
    });

  }

  public saveForm(): void {
    this._data.showSpinner();
    if (this.form.valid) {
      const { title, description , pricing } = this.form.value;
      const newProduct: Producto = {
        title: title,
        description: description,
        pricing: pricing,
        image: "https://celadasa.vteximg.com.br/arquivos/ids/156984-1000-1000/BQ7032-001.jpg",
        category: 'calzado',
        creationDate: new Date()

      }

      this._data.createProduct(newProduct).then(() => {
        this.form.reset();
        this._data.hideSpinner();
        this._data.showAlert('success', 'product', 'ok', false, 'center', 3500);

      });

    } else {
      this._data.hideSpinner();
      this._data.showAlert('error', 'form invalid', 'validad', false, 'center', 3500);
    }


  }


  delete(id) {
    this._data.showSpinner();
    this._data.deleteProduct(id).then(() => {
      this.form.reset();
      this._data.hideSpinner();
      this._data.showAlert('success', 'product delete', 'delete', false, 'center', 3500);

    });
  }
}

I am unsure whether the issue lies within the getProducts() function or elsewhere, or if I need to use pipes and maps.

Answer №1

Improving the function for listing products:

retrieveProducts(): Observable<Product[]> {
    this._firestore.collection<Product>(this.colProduct).valueChanges();
}


this._data.retrieveProducts().subscribe((data: Product[]) => {
  this.products = data;
});

Enhancement

Implementing Observable subscription within component template.html

my components.ts

public products: Product[] = [];

this._data.retrieveProducts().subscribe((data: Product[]) => {
      this.products = data;
    });
>>
public products$: Observable<Product[]>;

this.products$ = this._data.retrieveProducts();

my components.html

products
>> 
<div *ngFor="let product of products$ | async"
   /** Display each product item*/
  <div>

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

The 'posts' binding element is assumed to have a type of 'any' by default

Currently, I'm working on a code project that involves graphql, react, and typescript. In the middle of the process, I encountered an error message stating "Binding element 'posts' implicitly has an 'any' type." I am unsure about w ...

The API Gateway LogGroup is experiencing duplication issues and lacks critical details

I've been encountering difficulties setting up CloudWatch logs for my RestApi using cdk. Here is the code I'm using: const logGroup = new LogGroup(this, `apiLogs`, { logGroupName: `apiLogs`, retention: RetentionDays.ONE_WEEK }); ...

What is the best way to make mouse and touch events trigger responses in Angular versions 9 and above?

I've been searching high and low for a library or tried-and-true method to handle common user events reactively, but unfortunately my quest has come up empty. After some digging, I stumbled upon what seemed like a solid solution: https://github.com/t ...

Transforming a React component into a TypeScript Element results in an automatic 'any' type assignment due to the inability to index an expression of type 'string | number'

I am currently in the process of migrating a React component to TypeScript, but I have encountered an issue that I am struggling to resolve. I am consistently receiving an error related to accessing variantStyles[variant][color], and I cannot pinpoint the ...

Tips for setting up nested folders using Node.js on a Windows machine:

Is there a way to use Nodejs in Windows 10/11 to create a parent folder and then add a new folder inside of that parent folder, like this: parent/child within the Documents folder? ...

Trouble with Jest when trying to use route alias in Next.js with Typescript

Currently, I am developing a Next.js App (v13.2.3) using Typescript and have set up a path alias in the tsconfig.json. Does anyone know how I can configure the jest environment to recognize this path alias? // tsconfig.json { "compilerOptions": ...

Waiting for the execution of the loop to be completed before proceeding - Typescript (Angular)

There's a code snippet triggered on an HTML page when clicked: public salaryConfirmation() { const matDialogConfig: MatDialogConfig = _.cloneDeep(GajiIdSettings.DIALOG_CONFIG); this.warningNameList = []; for(let i=0; i < this.kelolaDat ...

Injecting pipes into directives in Angular: A guide

I've developed a custom directive that formats input values based on the provided pipe parameter (@Input) in Angular reactive forms. For this functionality, I had to import the necessary pipes (currently just one) and implement a switch mechanism to ...

Guide on implementing JWT authentication in API using Nebular Auth

I have implemented Nebular auth for my Angular application. I am trying to include a token in the header when a user logs in. Below is the API response: { "status": 0, "message": null, "data": { "type": &qu ...

What steps can I take to fix the 'node module error' while deploying a project on Vercel?

While working with the world-countries package, I encountered an issue during deployment in Vercel. The error message indicated that a ';' was missing in the index.d.ts file of world-countries located in the node_module directory. Here is the ex ...

Angular Express redirect and how to implement it

My SSR response service includes a redirect method along with other functionalities: import { Injectable, Inject } from '@angular/core'; import { Response } from 'express'; import { RESPONSE } from '@nguniversal/express-engine&ap ...

Guide to developing a dynamic method while utilizing IntelliSense assistance

When utilizing itemsApi in React reduxTool kit, dynamic functions like use..., mutate... are generated. These dynamically created methods possess complete intelligence as well. For instance, if you have createApi({... getItems: builder.query<any, st ...

Setting an optional property to null is not permitted

In my model class, I have defined an optional property as follows: export class Workflow { constructor( public id: number, public started: Date, public documentId: number, public document: Document, public status: WorkflowStatus, ...

typescript import { node } from types

Exploring the possibilities with an electron application developed in typescript. The main focus is on finding the appropriate approach for importing an external module. Here is my typescript configuration: { "compilerOptions": { "target": "es6", ...

Injecting data into mat-dialog-actions in Angular - how can it be done?

I have a question regarding passing data to a method in Angular. Below is the code snippet: Is there a way to pass data into addNpi() similar to how editNpi(data) is done below? Your help is appreciated. Thank you! <mat-dialog-content> <ip-dat ...

Typescript Code Coverage with karma-jasmine and istanbul: A complete guide

I am attempting to calculate the Code Coverage for my typescript Code in karma framework using Istanbul. In the karma.conf file, typescript files are added and through karma typescript-preprocessor we are able to conduct unit testing and code coverage of t ...

Trouble with Angular 2 template variable not being updated within ngSwitch

My code involves a variable called threadCount that is set based on user input and displayed on the same page. Everything works smoothly with regular interpolation <p>Threads: {{threadCount}}</p> But I also want to append it to specific thre ...

Steps for accessing the camera within a custom Ionic app

Currently, I am working on a unique custom application built using Ionic and Typescript. I have encountered an issue with opening the camera to capture a picture. While my app successfully opens the native camera for capturing photos, it unfortunately tak ...

Angular: You cannot assign a type of 'void' to a parameter that expects either a UserCredential or a Promise containing a UserCredential

Upon attempting to initiate a new method following a successful registration, I encountered an error in Webstorm: The argument type 'void' cannot be assigned to the parameter type '(value: UserCredential) => UserCredential | PromiseLik ...

Using TypeScript to structure and organize data in order to reduce the amount of overly complex code blocks

Within my TypeScript module, I have multiple array structures each intended to store distinct data sets. var monthlySheetP = [ ['Year', 'Month', 'Program', 'Region', 'Market', 'Country', &apo ...