Remove a record from Angular 2 Firebase collection

I've been searching extensively for a solution to this problem. Despite following the documentation on AngularFire 2 and Angular 2, I am unable to find a working answer. My goal is simply to delete a specific entry in my Firebase database using its unique key. Although I understand it can be done in Angular 4, I need to accomplish this task in Angular 2.

Any assistance provided would be immensely appreciated!

import { Component, OnInit } from '@angular/core';
import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';
import {Observable} from "rxjs/Observable";

@Component({
  selector: 'app-listings',
  templateUrl: './listings.component.html',
  styleUrls: ['./listings.component.scss']
})
export class ListingsComponent implements OnInit {
  items: Observable<any[]>;
  item: FirebaseObjectObservable<any[]>;
  constructor(db: AngularFireDatabase) {
    this.items = db.list('Harry');
    this.item = db.object('/Harry/');
  }
  delete() {
    this.item.remove(); // removes all data.
  }

  ngOnInit() {
  }
}

EDIT: Added the HTML

<ul class="list-group">
  <li class="list-group-item" *ngFor="let item of items | async">
    <p><strong>Name: </strong>{{item.name}}</p>
    <p><strong>Email: </strong>{{item.email}}</p>
    <p><strong>Mobile: </strong>{{item.mobile}}</p>
    <p><strong>Address: </strong>{{item.address}}</p>
    <div class="editDel row">
      <div class="col-sm-1"><button class="btn-primary">Edit</button></div>
      <div class="col-sm-1"><button class="btn-danger" (click)="delete()">Delete</button></div>
    </div>
  </li>
</ul>

EDIT: Added package versions

{
  "name": "ng2-firebase-addresslist",
  "version": "0.0.0",
  "license": "MIT",
  "angular-cli": {},
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "test": "ng test",
    "pree2e": "webdriver-manager update --standalone false --gecko false",
    "e2e": "protractor"
  },
  "private": true,
  "dependencies": {
    "@angular/common": "^2.3.1",
    "@angular/compiler": "^2.3.1",
    "@angular/core": "^2.3.1",
    "@angular/forms": "^2.3.1",
    "@angular/http": "^2.3.1",
    "@angular/platform-browser": "^2.3.1",
    "@angular/platform-browser-dynamic": "^2.3.1",
    "@angular/router": "^3.3.1",
    "angular2-flash-messages": "^1.0.8",
    "angularfire2": "^2.0.0-beta.7-pre",
    "core-js": "^2.4.1",
    "firebase": "^3.9.0",
    "rxjs": "^5.0.1",
    "ts-helpers": "^1.1.1",
    "zone.js": "^0.7.2"
  },
  "devDependencies": {
    "@angular/cli": "^1.4.4",
    "@angular/compiler-cli": "^2.3.1",
    "@types/jasmine": "2.5.38",
    "@types/node": "^6.0.42",
    "codelyzer": "~2.0.0-beta.1",
    "jasmine-core": "2.5.2",
    "jasmine-spec-reporter": "2.5.0",
    "karma": "1.2.0",
    "karma-chrome-launcher": "^2.0.0",
    "karma-cli": "^1.0.1",
    "karma-jasmine": "^1.0.2",
    "karma-remap-istanbul": "^0.2.1",
    "protractor": "~4.0.13",
    "ts-node": "1.2.1",
    "tslint": "^4.3.0",
    "typescript": "~2.0.3",
    "webpack": "^3.6.0"
  }
}

There seems to be a large discrepancy among guides and tutorials regarding this issue mainly due to different versions of AngularFire2 altering its functionality with each release. This inconsistency has been quite challenging for me as a learner.

Answer №1

After exploring different approaches, I found a unique solution to the problem.

I realized that by embedding this code in my HTML, I was able to access the specific key for each firebase object.

<p><strong>Item Key: </strong>{{item.$key}}</p>

Building on this, I integrated the key into my onClick function.

<button class="btn-danger" (click)="deleteObject(this.item.$key)">Delete</button>

This was then passed to my function in listings.components.ts

deleteObject(itemKey) {
 this.db.object('/Harry/' + itemKey).remove();
}

By implementing this process, I successfully removed the objects based on their individual keys. I appreciate the support from everyone here who assisted me throughout this journey. Additionally, I urge AngularFire2 to enhance its documentation for better guidance!

Answer №2

Attempt

elements: FirebaseListObservable<any[]>;

eliminate() {
  this.elements.remove(this.element)
}

Revise

A few other aspects seem off as well

constructor(db: AngularFireDatabase) {
    this.elements = db.list('Sally');
    this.element = db.object('/Sally/');
  }

should be

constructor(private db: AngularFireDatabase) {
    this.elements = this.db.list('Sally');
    this.element = this.db.object('/Sally/');
  }

You may want to also transfer the code in constructor to ngOnInit, as AngularFire might not be ready within the constructor. Not required, based on example linked below.

Revise #2

The template looks almost ok, but since elements is now FirebaseListObservable, need to access the iterated element with $value

<p><strong>Name: </strong>{{element.$value.name}}</p>
<p><strong>Email: </strong>{{element.$value.email}}</p>
<p><strong>Mobile: </strong>{{element.$value.mobile}}</p>
<p><strong>Address: </strong>{{element.$value.address}}</p>

Or, use

this.elements = db.list('Sally').valueChanges()
, as per this example in docs Example of persisting a Document Id

Revise #3

Since you have to rely on a specific release, I thought it might be beneficial to check out the source for the particular release (https://github.com/angular/angularfire2/releases). 2.0.0-beta.7, even though you may have 2.0.0-beta.8.

You may have heard the term 'documentation rots', which means better to look at code and specs when dealing with an older release.

The relevant spec is

describe('remove', () => {

    it('should call remove on the underlying ref', () => {
      var removeSpy = spyOn(ref, 'remove');

      O.subscribe();
      O.remove();
      expect(removeSpy).toHaveBeenCalledWith();
    });

    it('should throw an exception if removed when not subscribed', () => {
      O = new FirebaseObjectObservable((observer:Observer<any>) => {});

      expect(() => {
        O.remove();
      }).toThrowError('No ref specified for this Observable!')
    });

    it('should resolve returned thenable when successful', (done:any) => {
      O.remove().then(done, done.fail);
    });

  });

where O is equivalent to your this.element. Try adding this.element.subscribe() to your delete method.

Also, when you retrieve an item, why '/Sally/' and not '/Sally'?

And, you could wrap the operation in a promise to capture errors. From 'docs\2-retrieving-data-as-objects.md',

The promise can be useful to chain multiple operations, catching possible errors from security rules denials, or for debugging.

const promise = af.database.object('/item').remove();
  promise.then(_ => console.log('success'))
    .catch(err => console.log(err, 'You dont have access!'));

Answer №3


  <tbody>
        <tr *ngFor='let product of products | async'>
        <td>{{product.name}}</td>
        <td>{{product.description}}</td>
        <td>{{product.category}}</td>
        <td>{{product.price}}</td>
        <td>{{product.rating}}</td>
        <td>
            <div class="btn-group">
                <button (click)="deleteProduct(product)" class= "btn btn-danger"> delete </button> 
              
         </div>
        <td>  
        </tr>
    </tbody>

**

 - .ts file

**
deleteProduct(item: Product) {
    const confirmBox = confirm('Are you sure?');
    if (confirmBox) {
      this.productService.deleteProduct(item.id).then(() => {
        this.snackBar.open('Product has been deleted successfully...', 'close');
      });
    }
  }

**

 - service

**
  constructor(private fireStore: AngularFirestore) { }

deleteProduct(id: string): any {
    return this.fireStore.doc(`${this.collectionName}/` + id).delete();
  }

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

Using async-await in canActivate() within Angular 7

I am currently working on a code that verifies whether the browser contains user information. If not, the browser will make an API call to retrieve the user information from the server. Only users with valid information are granted access to navigate to di ...

Effortlessly adding custom classes in Angular 2 with a breeze

Imagine having a growing Angular2 typescript solution with numerous small classes and objects. Following the best practice, each class is placed in its own file. However, manipulating these objects leads to long lists of imports like: import {Object1} f ...

The module does not contain 'toPromise' as an exported member in rxjs version 5.5.2

Encountering an error when using toPromise Prior method: import 'rxjs/add/operator/toPromise'; Updated approach: import { toPromise } from 'rxjs/operators'; The new way is causing the following issues: [ts] Module '"d:/.../ ...

Expanding the typings for an established component in DefinitelyTyped

Is there a way to define new typings for additional props in DefinitelyTyped? After updating the material-ui library with some new props for the SelectField component, I realized that the typings in DefinitelyTyped are outdated. Is it possible to extend th ...

Transforming the window property in distinct entry points for TypeScript

During the initial page load, I am looking to transfer data from a template to a TypeScript file by attaching it to the window object. I want each page to utilize the same variable name for its specific data (window.data). An example of this can be seen in ...

Managing return types in functions based on conditions

Recently, I developed a function to map links originating from a CMS. However, there are instances where the link in the CMS is optional. In such cases, I need to return null. On the other hand, when the links are mandatory, having null as a return type is ...

Ways to display "No records" message when the filter in the material table in Angular returns no results

How can I implement a "No Records Message" for when the current table is displaying empty data? Check out this link for examples of material tables in AngularJS: https://material.angular.io/components/table/examples ...

Best location to define numerous dialog components

Currently, I have 8 custom Modals that are called in various places within my app. These modals are currently located inside the app.component.html as shown below: <agc class="app-content" [rows]="'auto 1fr'" [height]=" ...

What could be the reason for TypeScript being unable to recognize my function?

In my code, I have a Listener set up within an onInit method: google.maps.event.addListener(this.map, 'click', function(event) { console.log(event.latLng); var lt = event.latLng.lat; var ln = event.latLng.lng; co ...

Issue encountered when attempting to install Firebase via npm - SSL decryption error or faulty record MAC detected

I've been attempting to set up firebase but no matter what I try, I keep encountering the following Error: npm ERR! code ERR_SSL_DECRYPTION_FAILED_OR_BAD_RECORD_MAC npm ERR! errno ERR_SSL_DECRYPTION_FAILED_OR_BAD_RECORD_MAC npm ERR! Invalid response b ...

Guide to incorporating eslint with Next.js in a project that already has an eslint configuration

I recently created a new next.js project within my existing Node.js project, which already has an eslint config set up. Here's how the folder structure looks now: ...

"Unindexing data in Angular: A step-by-step guide

Can someone help me figure out how to delete an item by index in Angular? I have a parameter and a remove button, but when I tried putting my parameter inside the remove button it didn't work. How can I fix this? deleteRowFiles(rowIndex: number){ th ...

Issue with MongoDB $push within an Array of Arrays: The shorthand property 'elements' does not have a value available in scope

I am encountering an issue while trying to insert data into Elements in MongoDB using TypeScript. Any suggestions on how to resolve this problem? Attempt 1 Error: I am receiving an error message stating "No value exists in scope for the shorthand property ...

Is it necessary to sanitize input fields manually in Angular 6?

Is it necessary for me to manually sanitize all user inputs, or does Angular handle this process automatically? In my login form, the data is sent to the server upon submission. Do I need to explicitly sanitize the data, or does Angular take care of sanit ...

The initial rendering of components is not displayed by Vue Storybook

The functionality of the storybook is effective, but initially, it fails to "render" the component. By examining the screenshot, we can deduce that the component-template is being utilized in some way, as otherwise, the basic layout of the component would ...

Is there a way to conceal the progress output of an Angular build during test execution using Karma?

Currently, I am setting up a build process for an Angular 4 application and aiming to prevent progress output in order to keep the runner's logs clean. The project configurations were automatically created using angular cli (v1.0.1) By utilizing ng ...

Choose FormGroup using Angular Directive

Can Angular reactive form controls be selected for a custom directive in a different way? Take a look at this code snippet: @Directive({ selector: '[formControl], [formControlName]', }) export class MyDirective { constructor( priv ...

An unexpected runtime error occurred: TypeError - Unable to use map function on events

When fetching data using graphQL and rendering it on the page, an error occurs: Unhandled Runtime Error TypeError: events.map is not a function I'm unsure if my useState declaration is correct. const [events, setEvents] = useState < any > ([]) ...

Definition of union types in JavaScript using Typescript

Looking for assistance in creating a d.ts file for the union-type library found at https://github.com/paldepind/union-type Consider the following union type: let Maybe = Type({ Nothing: [] , Just: [Number] }) I am interested in setting up compi ...

Angular 6 Universal does not pause for resolver completion

I recently completed the installation of Angular Universal start kit version 6 and designed my component within it. The main purpose of this component is to retrieve user information from an API upon loading and display it on the view. The issue I am faci ...