【问题标题】:Angular 2 firebase database serviceAngular 2 firebase 数据库服务
【发布时间】:2017-05-16 03:21:12
【问题描述】:

我想在一个 Angular2 应用程序中提供一项服务,该服务可以完成所有数据库工作。我看到的所有教程都使用 http 而不是 firebase,所以它们并没有真正的帮助。我让服务构造函数从数据库中提取我需要的数据,但是当页面尝试从服务中获取数据时,它什么也得不到,因为数据库调用尚未完成。我开始觉得this post,将网络调用放在服务中没有任何意义,它们都应该是每个控制器中的重复代码,而不是将所有数据库代码放在一个服务中。这是我的文件:

lesson.service.ts

import { Injectable, OnInit } from '@angular/core';
import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';

export class Lesson {
  constructor(public id: number, public buttons: Object[]) {  }
}

@Injectable()
export class LessonService implements OnInit {

  private lessons: Lesson[] = [];
  constructor(public db: AngularFireDatabase) {
  }

  ngOnInit() {
    this.db.object('/lessons', { preserveSnapshot: true }).subscribe(lessons => {
      lessons.forEach(lesson => {
        this.lessons.push(new Lesson(
          lesson.key,
          lesson.val()['buttons']
        ));
      });
    });
  }

  getLessons() {
    console.log('getting lessons', this.lessons);
    return this.lessons;
  }

  getLesson(id: number): Lesson {
    // return new Promise()
    console.log('getLesson', this.lessons);
    return this.lessons.filter(lesson => {
      return lesson.id === id;
    })[0];
  }
}

lesson.ts

import { Component, OnInit, Input } from '@angular/core';
import { Lesson, LessonService } from '../lesson.service';

@Component({
  selector: 'lesson',
  templateUrl: './lesson.html',
  styleUrls: ['./lesson.scss']
})
export class LessonComponent implements OnInit {
  @Input() lessonID: number = 0;

  lesson: Lesson;
  constructor(public service: LessonService) {  }

  ngOnInit() {
    this.lesson = this.service.getLesson(this.lessonID);
    console.log('view lessons', this.lesson);
  }
}

lesson.html

<lesson [lessonID]="selectedId"></lesson>

当我尝试加载课程组件时,它发现没有课程​​,因为this.lessons 没有从服务的构造函数的数据库中填写。我看到的唯一“解决方案”是删除课程服务,并在每个页面加载时调用 DB,在我看来,这违背了做单页应用程序的目的。

【问题讨论】:

    标签: angular firebase firebase-realtime-database


    【解决方案1】:

    在 ngOnInit 中调用 getLesson 作为 您注入的服务也可能仍在初始化。

    我之前的代码也有同样的问题,但在将代码移至 ngAfterViewInit(),它解决了这个问题。

    import { Component, OnInit, AfterViewInit } from '@angular/core';
    ...
    ...
    
    export class LessonComponent implements OnInit, AfterViewInit {
      @Input() lessonID: number = 0;
    
      lesson: Lesson;
      constructor(public service: LessonService) {  }
    
      ngOnInit() {
    
      }
    
      ngAfterViewInit() {
       this.lesson = this.service.getLesson(this.lessonID);
        console.log('view lessons', this.lesson);
      }
    }
    

    【讨论】:

    • 我试过这个,但仍然有同样的问题,我想我今天通过从视图调用 getLessons() 来让它在个人项目中工作,它从服务调用 getLessons()。我将在星期一恢复工作时回答我的问题以供参考。它有效,但不知何故感觉不对,但我有点喜欢它的工作原理。
    【解决方案2】:

    我想我发布了错误的 ts 和 html 文件,但我发布的文件仍然存在问题。您可以通过这些文件看到更多问题,这就是我为修复它所做的。我从一直到服务的视图调用一个函数。我猜这是一种不好的做法,但这是我发现的唯一可行的方法。

    lesson.service.ts

    import { Injectable, OnInit } from '@angular/core';
    import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';
    
    export class Lesson {
      constructor(public id: number, public buttons: Object[]) {  }
    }
    
    @Injectable()
    export class LessonService implements OnInit {
    
      private lessons: Lesson[] = [];
      public buttons: object[];
      constructor(public db: AngularFireDatabase) {
        this.db.object('/lessons', { preserveSnapshot: true }).subscribe(lessons => {
          this.lessons = [];
          lessons.forEach(lesson => {
            this.lessons.push(new Lesson(
              lesson.key,
              lesson.val()['buttons']
            ));
          });
        });
      }
    
      ngOnInit() {
      }
    
      getLessons() { return this.lessons; }
    
      getLesson(id: number): Lesson {
        return this.lessons.filter(lesson => {
          return lesson.id === id;
        })[0];
      }
    
    }
    

    lesson.ts

        import { Component } from '@angular/core';
    import { Router, ActivatedRoute, Params } from '@angular/router';
    import { Lesson, LessonService } from './lesson.service';
    
    @Component({
      selector: 'app-root',
      templateUrl: './app.component.html',
      styleUrls: ['./app.component.scss']
    })
    export class AppComponent {
      private lessons: Lesson[];
      private lesson: Lesson = new Lesson(0, []);
      private errorMessage: string;
      constructor(
        private route: ActivatedRoute,
        private router: Router,
        private service: LessonService
      ) {}
    
      getLessons() { return this.service.getLessons(); }
    
      gotoLesson(id) { this.router.navigate(['/lesson', id]); }
    
      getButtons() { return this.service.buttons; }
    
      doCLick(btnID) {
        console.log('clicked', btnID);
      }
    }
    

    lesson.html

    <md-toolbar>
      <button md-button routerLink="" routerLinkActive="active">Home</button>
      <button md-button [mdMenuTriggerFor]="lessonsMenu">Lessons </button>
      <md-menu #lessonsMenu="mdMenu" [overlapTrigger]="false">
        <button md-menu-item *ngFor="let lesson of getLessons()" (click)="gotoLesson(lesson.id)">Lesson {{lesson.id}}</button>
      </md-menu>
      <span class="toolbar-spacer"></span>
      <button md-mini-fab color="primary" *ngFor="let button of getButtons()" (click)="doClick(button.id)" style="margin-right: 10px;">
        <md-icon>{{button.icon}}</md-icon>
      </button>
      <button md-mini-fab style="margin-left: 10px;">
        <md-icon>search</md-icon>
      </button>
    </md-toolbar>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-16
      • 1970-01-01
      • 1970-01-01
      • 2017-03-17
      • 2017-04-15
      • 1970-01-01
      • 2018-02-23
      • 2017-06-29
      相关资源
      最近更新 更多