Reputation: 3393
What I have and what I'm trying to do
Questions
I"ve included the firebase suggested approach at the very bottom. It would be fantastic to know how to integrate that into my current structure.
Album Service
import { Injectable } from '@angular/core';
import { Album } from './album.model';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
@Injectable()
export class AlbumService {
albums: FirebaseListObservable<any[]>;
constructor(private database: AngularFireDatabase) {
this.albums = database.list('albums');
}
getAlbums() {
return this.albums;;
}
addAlbum(newAlbum: Album) {
this.albums.push(newAlbum);
}
getAlbumById(albumId: string) {
return this.database.object('/albums/' + albumId);
}
updateAlbum(localUpdatedAlbum) {
var albumEntryInFirebase = this.getAlbumById(localUpdatedAlbum.$key);
albumEntryInFirebase.update({
title: localUpdatedAlbum.title,
artist: localUpdatedAlbum.artist,
description: localUpdatedAlbum.description
});
}
}
Admin.component.html - Used to add new items
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Add New Album to Inventory</h3>
</div>
<div class="panel-body">
<div>
<div>
<label>Album Title:</label>
<br>
<input #newTitle>
</div>
<div>
<label>Album Artist:</label>
<br>
<input #newArtist>
</div>
<div>
<label>Album Description:</label>
<br>
<textarea #newDescription></textarea>
</div>
<button (click)="submitForm(newTitle.value, newArtist.value, newDescription.value); newTitle.value=''; newArtist.value=''; newDescription.value=''">Add</button>
</div>
</div>
</div>
Admin.component.ts - used to add new items
import { Component, OnInit } from '@angular/core';
import { Album } from '../album.model';
import { AlbumService } from '../album.service';
import { AngularFireDatabase, FirebaseListObservable } from 'angularfire2/database';
@Component({
selector: 'app-admin',
templateUrl: './admin.component.html',
styleUrls: ['./admin.component.css'],
providers: [AlbumService]
})
export class AdminComponent implements OnInit {
constructor(
private albumService: AlbumService
) { }
ngOnInit() {
}
submitForm(title: string, artist: string, description: string) {
var newAlbum: Album = new Album(title, artist, description);
this.albumService.addAlbum(newAlbum);
console.log(newAlbum);
}
}
This is the code firebase suggest for updating information and pushing through the unique firebase key for each new node
// A post entry
var postDate = {
author: username,
body:body,
title:title
}
// Get a key for a new post
var newPostKey = firebase.database().ref().child('posts').push().key;
// Write the new post's data simultaneously in the posts list and the user's post list
var udpates = {}
updates['/posts' + newPostKey] = postData;
updates['/users-posts/' + newPostKey] = postData;
return firebase.database().red().update(updates);
edit:
admin component.ts
The below code causes what's seen in the image. So we're getting incredibly close. Whenever i include '(key)', the following error is thrown:
[ts] Cannot invoke an expression whose type lacks a call signature. Type 'FirebaseListObservable' has no compatible call signatures.
submitForm(title: string, artist: string, description: string) {
var newAlbum: Album = new Album(title, artist, description);
//this.albumService.addAlbum(newAlbum);
console.log(newAlbum);
var albumListObject = {
title:title,
description:description
}
this.albumService.albums.push(newAlbum).then(({key}) => this.albumService.summariesObject.push(albumListObject));
}
}
Album Service
import { Injectable } from '@angular/core';
import { Album } from './album.model';
import { AngularFireDatabase, FirebaseListObservable, FirebaseObjectObservable} from 'angularfire2/database';
@Injectable()
export class AlbumService {
albums: FirebaseListObservable<any[]>;
summariesObject: FirebaseObjectObservable<any[]>;
constructor(private database: AngularFireDatabase) {
this.albums = database.list('albums');
this.summariesObject = database.object('albumList');
}
}
Questions
Upvotes: 1
Views: 3235
Reputation:
A lot of this is a matter of preference and style. Having said that, it is almost always going to be a better idea to isolate firebase-specific actions in one or more services.
However, I wonder it it's really worthwhile to define a lot of methods like addAlbum
My personal preference is to have the service simply provide a FirebaseListObservable
, and do the .push
directly in the component. There may be those who find an additional layer of abstraction desirable--they may, for example, paint a scenario where you are switching from Firebase to something else. However, in practice, that's unlikely and if you did decide to do that this kind of simple abstraction layer would not help you that much anyway.
As a minor point, if you have an entire service dedicated to albums, I don't find it necessary to repeat the word "album" in all the method names. Why not just add()
?
The standard pattern for pushing a new object onto one node and then creating a sub-node somewhere else with the same key is
this.albumService.list.push(albumData)
.then(({key}) => this.albumService.summariesObject(key).update(stuff));
In other words, push the data to the list, generating a new key, wait for the promise to fulfill with a snapshot which will contain a key, then update a FirebaseObjectObservable
for an object with that key inside some other node with the necessary data. It's better to try to stay within the AngularFire paradigm, although granted there are cases where you have to fall back to firebase.database().ref
kinds of things.
Upvotes: 4