Angular& Firebase - 如何更新firebase:使用服务还是在组件中?

时间:2017-07-01 17:30:48

标签: angular firebase angularfire angular-services

我拥有什么以及我想做什么

  • 我有一项服务,可以获得一系列相册'来自firebase
  • 我有一个组件,其中包含一些用于添加新项目的输入字段
  • 作为firebase非正规化数据的一部分,我有两个想要更新的节点。 ' AlbumLists'和' AlbumDetails'
  • 我可以使用下面的代码更新到firebase(不包括最底层的firebase建议)
  • 我知道我可能需要在我的示例中包含其他服务。一个用于专辑列表,一个用于专辑摘要

问题

  1. 我已经看过firebase的一些示例代码,介绍如何在多个位置更新代码并为两个新节点创建新密钥。但是,我不知道这个代码在我当前的解决方案中会在哪里。它是在组件还是服务中?
  2. 如果代码适合组件,是否值得提供服务? (如果它可以在我的服务中工作,那就太好了)
  3.   

    我已经在最底层包含了firebase建议的方法。知道如何将其整合到我当前的结构中会很棒。

    相册服务

    
    
    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      
        });
      }
    
    }
    &#13;
    &#13;
    &#13;

    Admin.component.html - 用于添加新项

    &#13;
    &#13;
    <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>
    &#13;
    &#13;
    &#13;

    Admin.component.ts - 用于添加新项

    &#13;
    &#13;
    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);
    
      }
    
    }
    &#13;
    &#13;
    &#13;

    这是代码firebase建议更新信息并推送每个新节点的唯一firebase密钥

    &#13;
    &#13;
    // 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);
    &#13;
    &#13;
    &#13;

    编辑

    admin component.ts

    以下代码会导致图片中显示的内容。所以我们变得非常接近。每当我包含&#39;(键)&#39;时,都会抛出以下错误:

      

    [ts]无法调用类型缺少调用签名的表达式。输入&#39; FirebaseListObservable&#39;没有兼容的呼叫签名。

    &#13;
    &#13;
      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));
    
      }
    
    }
    &#13;
    &#13;
    &#13;

    相册服务

    &#13;
    &#13;
    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');
      }
    }
    &#13;
    &#13;
    &#13;

    enter image description here

    问题

    1. 在我的相册服务中,我是否需要为albumList和Summaries提供两个firebase引用?或者他们会在两种不同的服务中?
    2. 为什么(键)文本会导致错误?

1 个答案:

答案 0 :(得分:4)

很多这是偏好和风格的问题。话虽如此,在一个或多个服务中隔离特定于firebase的操作几乎总是更好的主意。

但是,我不知道定义很多方法是非常值得的,例如addAlbum我的个人偏好是让服务只提供FirebaseListObservable,并直接执行.push组件。可能会有人发现需要额外的抽象层 - 例如,他们可能会描绘您从Firebase切换到其他内容的场景。然而,在实践中,这是不太可能的,如果你确实决定这样做,那么这种简单的抽象层无论如何也无助于你。

作为一个小问题,如果您有专门用于专辑的整个服务,我认为没有必要在所有方法名称中重复“专辑”一词。为什么不只是add()

将新对象推送到一个节点然后使用相同密钥在其他位置创建子节点的标准模式是

this.albumService.list.push(albumData)
  .then(({key}) => this.albumService.summariesObject(key).update(stuff));

换句话说,将数据推送到列表,生成一个新密钥,等待承诺使用包含密钥的快照来实现,然后为某个对象更新FirebaseObjectObservable其他节点有必要的数据。最好尽量保持在AngularFire范式内,尽管有些情况下你必须回归firebase.database().ref种事物。