6

The question has been answered but I'm looking for a, um, more straightforward one if available. It seems strange that we'd have to implement not one but two mappings just to have access to the object keys.

basic firebase db: enter image description here As can be seen, the course objects clearly have keys. Mark-up:

<ul>
  <li *ngFor="let course of courses$ | async">
    <b>Key:</b> {{course.$key}} <!-- doesn't show --!>
    <b>Title:</b> {{course.Title}}
    <b>Duration:</b> {{course.Duration}}
    <b>Author:</b> {{course.Author}}
    <p><button (click)="deleteCourse(course)">Remove</button></p>

    <hr> 
  </li>
</ul>

Now, the courses display just fine, but I don't know how to get a reference to the key in order to delete it. (Or perhaps I'm not using the right method on my firebaseDatabase Object). Either way, when I log the key in the console, it shows as undefined.

export class AppComponent {
  courses;
  courses$: AngularFireList<any>;

  constructor(private db: AngularFireDatabase) {
    this.courses = db.list('/courses');
    this.courses$ = this.courses.valueChanges();
  }
  ...
  deleteCourse(course) {
    console.log(course.$key); // -> undefined
    this.db.object('/courses/' + course.$key).remove();
  }
}

2 Answers 2

20

Updated Answer

Rxjs have changed how it pipes data. now you have to use .pipe().

this.courses$ = this.courses.snapshotChanges().pipe(
  map(changes => 
    changes.map(c => ({ key: c.payload.key, ...c.payload.val() }))
  )
);

Original Answer

.valueChanges() contain simply data, no key with it. you need to use .snapshotChanges()

this.courses$ = this.courses.snapshotChanges().map(changes => {
  return changes.map(c => ({ key: c.payload.key, ...c.payload.val() }));
});

now just use {{course.key}}

here is your corrected code

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/map';

export class AppComponent {
  courseRef: AngularFireList<any>;
  courses$: Observable<any[]>;

  constructor(private db: AngularFireDatabase) {
    this.courseRef = db.list('/courses');
    this.courses$ = this.courseRef.snapshotChanges().map(changes => {
        return changes.map(c => ({ key: c.payload.key, ...c.payload.val() 
    }));
   });
  }
  ...
  deleteCourse(course) {
    console.log(course.key);
    this.db.object('/courses/' + course.key).remove();
  }
}
Sign up to request clarification or add additional context in comments.

6 Comments

No need for the entire module, but hey, Thanks! Jeez that's a lot of work to do to just retain the key. Used to be so much easier with earlier versions of Firebase!
Still showing the key as undefined in the console. And of course, not deleting
which version of angularfire2?
you still using {{course.$key}} it should be {{course.key}} in the demo app
@Hareesh Can You Please explain what is happening in the first snippet especially how we get the key?
|
1

to create an interface:

export interface Client{
    key?: string;
    firstName?: string;
    lastName?: string;
    email?: string;
    phone?: string;
    balance?:number;

}

import { Injectable } from '@angular/core';
import { AngularFireDatabase, AngularFireList, AngularFireObject} from '@angular/fire/database';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';



@Injectable()
export class ClientService {
  client: AngularFireList<any>;
  clients: Observable<any[]>;

  constructor(public db: AngularFireDatabase) {
    this.client = db.list('/clients');
    this.clients = this.client.snapshotChanges().pipe(
      map(res => res.map(c => ({ key: c.payload.key, ...c.payload.val() 
    }))

   ));

  }

  getClients(){
    return this.clients;
  }


}

import { Component, OnInit } from '@angular/core';
import { ClientService } from '../../services/client.service';
import { Client} from '../../models/client'



@Component({
  selector: 'app-clients',
  templateUrl: './clients.component.html',
  styleUrls: ['./clients.component.css']
})
export class ClientsComponent implements OnInit {
  clients:Client[];

  constructor(
    public clientService:ClientService
  ) { }

  ngOnInit(){
    this.clientService.getClients().subscribe(clients=>{
      this.clients = clients;
      console.log(this.clients);
    })


  }

}

2 Comments

This worked for me to retrieve the key(metadata) and the values at once.
Hi @Pushpa Raj Panthi, welcome to stackoverflow! You're answering a question which is over 2 years old. Please try to answer new questions, this would be more helpful. And don't comment your own answer. Write this directly into the answer field. You're able to edit the answer below the answer box.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.