Harry
Harry

Reputation: 380

Delete Firebase entry angular 2

I've looked for quite a bit for an answer to this question. Followed documentation on AngularFire 2 and Angular 2 itself but I can't find a working answer. I simply want to delete an entry in my firebase database using the unique key. I could probably do this in Angular 4 but I'm having to do this for Angular 2.

Any support would be greatly 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"
  }
}

So I've noticed a lot of the guides and tutorials differ wildly on this topic mostly because different versions of AngularFire2 change how this works each time. An issue which has caused a lot of frustration for someone like myself who is learning.

Upvotes: 1

Views: 7388

Answers (3)

ANKIT MISHRA
ANKIT MISHRA

Reputation: 606

  <tbody>
        <tr *ngFor='let item of items | async'>
        <td>{{item.in}}</td>
        <td>{{item.des}}</td>
        <td>{{item.cast}}</td>
        <td>{{item.tomi}}</td>
        <td>{{item.ris}}</td>
        <td>
            <div class="btn-group">
                <button (click)="deleteItem(item)" class= "btn btn-danger"> delete </button> 
              
         </div>
        <td>  
        </tr>
    </tbody>

**

 - .ts file

**
deleteItem(user: User) {
    const confirmBox = confirm('Are you sure?');
    if (confirmBox) {
      this.service.deleteUser(user.id).then(() => {
        this.snackBar.open('visitor has been deleted successfully...', 'close');
      });
    }
  }

**

 - service

**
  constructor(private fireStore: AngularFirestore) { }

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

Upvotes: 0

Harry
Harry

Reputation: 380

So I solved it using a slightly different method.

I noticed posting this in my HTML gave me my individual key for each firebase object.

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

So I then took it a step further and included it in my onClick function.

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

Which I then fed into my function in listings.components.ts

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

That successfully ended up removing the objects by their key one-by-one! Thanks for everyones support here that helped me along the way. Also AngularFire2, get better documentation!!!

Upvotes: 2

Richard Matsen
Richard Matsen

Reputation: 23463

Try

items: FirebaseListObservable<any[]>;

delete() {
  this.items.remove(this.item)
}

Edit

A couple of other things don't look quite right

constructor(db: AngularFireDatabase) {
    this.items = db.list('Harry');
    this.item = db.object('/Harry/');
  }

should be

constructor(private db: AngularFireDatabase) {
    this.items = this.db.list('Harry');
    this.item = this.db.object('/Harry/');
  }

You may want to also move the code in constructor to ngOnInit, as AngularFire might not be ready within the constructor. Not necessary, according to example linked below.

Edit #2

The template looks almost ok, but because items is now FirebaseListObservable, need to access the iterated item with $value

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

Or, use this.items = db.list('Harry').valueChanges(), as per this example in docs Example of persisting a Document Id

Edit #3

Since you have to use a specific release, I thought it might be useful to take a look at the source for the specific release (https://github.com/angular/angularfire2/releases). 2.0.0-beta.7, although 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 relevent 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.item. Try is adding this.item.subscribe() to your delete method.

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

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!'));

Upvotes: 1

Related Questions