刷新时局部变量未定义。 Angular 2

时间:2017-09-24 02:13:13

标签: javascript angular firebase

我正在开发聊天应用程序。有一个chat.component.ts连接到服务并抓取'messages'和'displayName'。

在chat.component.html中绑定displayName,如下所示: <p>You are logged in as: {{displayName}}</p>

这就是chat.component.ts的样子:

import { Component, OnInit, AfterViewChecked, ViewChild, ElementRef } from '@angular/core';
import { AfService } from '../af.service';
import { FirebaseListObservable } from 'angularfire2/database';

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

  public newMessage: string;
  public messages: FirebaseListObservable<any>;
  public displayName: string;

  constructor(public AF: AfService) {
    this.messages = this.AF.messages;
    this.displayName = this.AF.displayName;
  }

  ngOnInit() {}

  @ViewChild('scrollMe') private myScrollContainer: ElementRef;

  ngAfterViewChecked() {
    this.scrollToBottom();
  }

  scrollToBottom(): void {
    try {
      this.myScrollContainer.nativeElement.scrollTop = this.myScrollContainer.nativeElement.scrollHeight;
    } catch(err) { console.log('Scroll to bottom failed yo!')}
  }

  isMe(email) {
    if(email == this.AF.email)
      return true;
    else
      return false;
  }

  sendMessage(){
    this.AF.sendMessage(this.newMessage);
    this.newMessage = '';
  }
}

AfService中的displayName属性是从前一个组件设置的。

现在这就是问题:

当我从头开始处理应用程序并登录时,displayName可用。但是,当我刷新chat.component.html页面时,displayName变为未定义。例如,如果我执行console.log(this.AF.displayName),它会显示为,但是,如果我执行console.log(this.displayName),则它是未定义的。

有趣的是,'messaages'保持正常运作。

我认为这更像是一个概念性问题,我想弄清楚为什么会发生这种情况以及如何解决这个问题。此外,我无法为这个问题找到更好的标题。

更新,这是AfService:

import { Injectable } from '@angular/core';
import { AngularFireDatabase } from 'angularfire2/database';
import { AngularFireAuth } from 'angularfire2/auth';
import { FirebaseListObservable } from 'angularfire2/database';
import { Observable } from 'rxjs/Observable';
import * as firebase from 'firebase/app';

@Injectable()
export class AfService {

  user: Observable<firebase.User>;
  messages: FirebaseListObservable<any>;
  displayName: string;
  email: string;

  constructor(public db: AngularFireDatabase, public afAuth: AngularFireAuth) {
    this.messages = this.db.list('messages');
  }

  loginWithGoogle(){
    return this.afAuth.auth.signInWithPopup(new firebase.auth.GoogleAuthProvider());
  };

  logout(){
    this.afAuth.auth.signOut();
  };

  sendMessage(text) {
    var message = {
      message: text,
      displayName: this.displayName,
      email: tis.email,
      timestamp: Date.now()
    };
    this.messages.push(message);
  };

  getDisplayName() {
    return this.displayName;
  }
}

3 个答案:

答案 0 :(得分:2)

因此,虽然我同意amal的评论并且无法查看this.displayName的设置位置。我以前遇到过这个问题。由于没有以前的组件,您需要一种方法让页面保存显示名称。我通常使用本地存储来执行此操作。

      localStorage.setItem('displayName',JSON.stringify(this.displayName));

检索数据和

    this.displayName= JSON.parse(localStorage.getItem('displayName'));

检索数据。话虽如此,我不知道你在哪里设置域名,这会导致问题。我正在回答你关于刷新的一般概念性问题。

答案 1 :(得分:0)

如果我理解正确,您应该在AfService

中订阅身份验证服务
constructor(public db: AngularFireDatabase, public afAuth: AngularFireAuth) {
    this.messages = this.db.list('messages');

    this.afAuth.auth.subscribe(res => {
        if (res && res.uid) {
          //user logged in
          this.email= res.email;
          this.displayName = res.displayName;
        } else {
          //user not logged in or logged out
        }
     });
}

答案 2 :(得分:0)

好。现在很清楚为什么messages可用,而displayName不在您的ChatComponent中。在AFService的构造函数中,您设置的值为messages,但不是displayName。因此,当在ChatComponent中实例化该服务时,您将组件的messagesdisplayName属性设置为来自AFService的属性。但是AFService只在其自己的构造函数中具有messages的值。 因此,对问题的简单修复就是在服务的构造函数中定义displayName的值。 如果需要从异步的其他地方获取该值,则需要根据该值重构组件或服务的代码。 无论哪种方式,都要确保引用在其构造函数中实例化的AFService的某些属性,同时在ChatComponent中引用它。