【问题标题】:Angular & Firebase - How to update firebase: With a service or in a component?Angular 和 Firebase - 如何更新 firebase:使用服务还是在组件中?
【发布时间】:2017-07-01 17:30:47
【问题描述】:

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

  • 我有一项服务可以从 firebase 获取“专辑”列表
  • 我有一个组件,其中包含一些用于添加新项目的输入字段
  • 作为 Firebase 数据非规范化的一部分,我有两个要更新的节点。 “专辑列表”和“专辑详情”
  • 我可以使用下面的代码更新到 firebase(不包括最底部的 firebase 建议)
  • 我知道我可能需要在我的示例中包含另一个服务。一个用于专辑列表,一个用于专辑摘要

问题

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

我已经在最底部包含了 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      
    });
  }

}

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

<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 - 用于添加新项目

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

  }

}

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

// 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);

编辑:

管理组件.ts

下面的代码会导致图像中出现的情况。所以我们变得难以置信地接近。每当我包含'(key)'时,都会引发以下错误:

[ts] 无法调用类型缺少调用签名的表达式。类型“FirebaseListObservable”没有兼容的调用签名。

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

  }

}

相册服务

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

问题

  1. 在我的专辑服务中,我需要为专辑列表和摘要提供两个 Firebase 引用吗?还是他们会分属两种不同的服务?
  2. 为什么(键)文本会导致错误?

【问题讨论】:

    标签: angular firebase angularfire angular-services


    【解决方案1】:

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

    但是,我不知道定义很多方法真的值得吗addAlbum 我个人的偏好是让服务简单地提供一个FirebaseListObservable,并直接在组件中执行.push。有些人可能会发现需要额外的抽象层——例如,他们可能会描绘一个场景,您正在从 Firebase 切换到其他东西。但是,在实践中,这不太可能,如果您确实决定这样做,那么这种简单的抽象层无论如何也对您没有太大帮助。

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

    将新对象推送到一个节点,然后在其他地方使用相同的键创建子节点的标准模式是

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

    换句话说,将数据推送到列表中,生成一个新的键,等待承诺完成一个包含键的快照,然后在其他节点内为具有该键的对象更新FirebaseObjectObservable与必要的数据。最好尝试保持在 AngularFire 范式内,尽管在某些情况下您必须退回到 firebase.database().ref 之类的东西。

    【讨论】:

    • 您好 Torazaburo - 感谢您抽出宝贵时间回复。非常感激。避开 .firebase.database 会很好(主要是因为无论如何,我都会不断收到“找不到 firebase”)。如果不是太麻烦,您能否向我展示一个示例,说明您的代码如何与上面的代码相匹配? (如前所述,对这一切都非常陌生,并试图弄清楚所有部分是如何组合在一起的)
    • 想象在提交表单方法中我想将标题、艺术家和描述推送到 firebase 专辑节点,我想将标题和艺术家推送到专辑列表 firebase 节点。但是专辑 > 键 / 专辑列表 > 键(两个键相同)
    • 另外,我更喜欢让服务提供数据并在组件中进行推送的想法。我认为更新也是一样的
    • @MetaTron 是的,update(和 remove)也一样。
    • 谢谢虎三郎。我很珍惜时间。在尝试集成您的更改时,我已经包含了一个编辑。在这里的任何帮助将不胜感激。我会给你发邮件给你啤酒什么的,感觉很接近:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多