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

Encountered an issue while using OpenAPI 3.1 with openapi-generator-cli typescript-fetch. Error: JsonParseException - The token 'openapi' was not recognized, expected JSON String

I am interested in creating a TypeScript-fetch client using openapi-generator-cli. The specifications were produced by Stoplight following the OpenAPI 3.1 format. However, when I execute the command openapi-generator-cli generate -i resources/openapi/Attri ...

How do I customize the alert in ion-select using IONIC ANGULAR?

How can I create a select element like this: Is it possible to customize the selected item? I'm new to working with Ionic. I've tried using custom properties, but they don't seem to work as expected. I also attempted a fake select by using ...

How can I display JSON values without revealing the parent in Angular 5 and Ionic 3?

I am trying to extract values from JSON without the parent keys. Here is the JSON structure I have: [ { "companies": [{ "id": 1, "name": "Prueba", "company_number": "23423423A", "latitude": 241241.12, "lo ...

Accessing the URL causes malfunctioning of the dynamic routing in Angular 2

I am currently working on implementing dynamic routing functionality in my Angular application. So far, I have successfully achieved the following functionalities: Addition of routing to an existing angular component based on user input Removal of routin ...

Show the user's chosen name in place of their actual identity during a chat

I'm facing an issue where I want to show the user's friendly name in a conversation, but it looks like the Message resource only returns the identity string as the message author. I attempted to retrieve the conversation participants, generate a ...

bsDatepicker restricts the selection of dates after the endDate

I'm attempting to set the minDate for endDate inputs to be one day after startDate's value. Can anyone spot what I'm doing wrong? Check out stackblitz .ts this.minendDate.setDate(this.minendDate.getDate() + 1); this.maxendDate.setDate(this ...

Angular module cannot be located

While working on implementing a chat feature for my project using sockJS and STOMP, I encountered several challenges with installing these two libraries. Despite attempting various methods such as installation from index.html, npm install, and manual downl ...

Error TS2304: Unable to locate identifier 'QRScanner'

I am currently exploring https://www.npmjs.com/package/cordova-plugin-qrscanner in order to implement a QR scanning feature in my mobile application. As part of the initial steps, I have written the following code snippet in my typescript file: function o ...

Issue: ng test encountered a StaticInjectorError related to FormBuilder

I recently started using ng test to run tests on my Angular application. I utilized the Angular-Cli tool to create modules and components, and the .spec.ts files were generated automatically. During one of the tests, I encountered the following error: ...

Encountered an error with NEXT JS: npm ERR! - error code ERR_SOCKET

npm ERR! code ERR_SOCKET_TIMEOUT npm ERR! network Socket timeout npm ERR! network This issue is related to problems with your network connectivity. npm ERR! network Typically, being behind a proxy or having incorrect network settings can cause this error. ...

Retrieve the value of the Observable when it is true, or else display a message

In one of my templates, I have the following code snippet: <app-name val="{{ (observable$ | async)?.field > 0 || "No field" }}" The goal here is to retrieve the value of the property "field" from the Observable only if it is grea ...

Creating a data structure that consists of pairs of elements, inspired by the alignment of domino bricks, using TypeScript syntax

My goal is to establish a type alias in TypeScript that allows all values which are arrays of Domino pairs, where each pair connects like domino bricks: Pair<A,B> connects with Pair<C,D> only if B = C. For example: const chain1: DominoChain = ...

Navigating through a complex firebase function structure

Hey there, I'm new to cloud functions and could use some help. I'm attempting to create a cascader that includes categories and their subcategories, but I'm not getting the expected response. After sending the response, all the values in ca ...

Setting up a Variable with an Object Attribute in Angular

I am attempting to create a variable that will set a specific property of an object retrieved through the get method. While using console.log in the subscribe function, I am able to retrieve the entire array value. However, as a beginner, I am struggling ...

Looping through an array of nested objects using Vue

I have encountered a challenge with accessing specific data within an array that I am iterating over. The array is structured as follows, using Vue.js: companies: [ name: "company1" id: 1 type: "finance" additionalData: "{& ...

Encountering issues with Google authentication functionality while using AngularFire2

Currently in the process of setting up Google Authentication with Firebase and AngularFire2. The setup seems to be partially functional, however, there are some unusual behaviors that I am encountering. Upon the initial loading of the app, the Login button ...

Utilizing data from the home component in another component: A guide

Here is the code I am working with, showcasing how to utilize (this.categoryType) in another component: getCategoryDetails(){ return this.http.get('ip/ramu/api/api/…') .map((res:Response) => res.json()); } The above code snippet is utilize ...

What is the best way to implement CSS Float in typescript programming?

For a specific purpose, I am passing CSS Float as props. To achieve this, I have to define it in the following way: type Props = { float: ???? } const Component = ({ float }: Props) => {......} What is the most effective approach to accomplish this? ...

Utilizing precise data types for return values in React hooks with Typescript based on argument types

I developed a react hook that resembles the following structure: export const useForm = <T>(values: T) => { const [formData, setFormData] = useState<FormFieldData<T>>({}); useEffect(() => { const fields = {}; for (const ...

determining the properties of a given data type

I am currently working with a type that I have obtained from a third party source. My goal is to determine the type of a specific property within that type, using TypeScript. For example: type GivenType = { prop: string; } type desiredType = <&l ...