Angular 4 UI 未从可观察订阅更新

标签 angular angular2-services

我在我的应用程序组件中订阅的服务中有一个 observable。数据通过订阅传递没有问题,但由于某种原因我无法让 UI 更新新信息。我知道数据已到达那里,因为它已被记录到控制台。

这是我的 app.component 代码:

import {Component, OnDestroy, OnInit} from '@angular/core';
import {UserDetailsService} from './services/user-details.service';
import {User} from './shared/models/user';
import {Subscription} from 'rxjs/Subscription';

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

  title = 'the Portfolio';
  user: User;
  userSub: Subscription;

  constructor(public userDetails: UserDetailsService) {
  }

  ngOnInit(): void {
    this.userSub = this.userDetails.user$.subscribe(user => {
      this.user = user;
      console.log(user);
    });
  }

  ngOnDestroy() {
    this.userSub.unsubscribe();
  }
}

我更新可观察对象的用户登录组件:

import {Component, AfterViewInit, NgZone} from '@angular/core';
import {UserDetailsService} from '../services/user-details.service';
import {User} from '../shared/models/user';

declare const gapi: any;

@Component({
  selector: 'app-user-login',
  templateUrl: './user-login.component.html',
  styleUrls: ['./user-login.component.css']
})

export class UserLoginComponent implements AfterViewInit {

  constructor(private _zone: NgZone, private userDetails: UserDetailsService) {
    console.log(this);
  }

  ngAfterViewInit() {
    gapi.load('auth2', () => {
      const auth = gapi.auth2.init({
        'clientId': 'YOURID.apps.googleusercontent.com'
      });

      auth.attachClickHandler('google-login-button', {},
        (googleUser) => {
          const profile = googleUser.getBasicProfile();
          // console.log('Token || ' + googleUser.getAuthResponse().id_token);
          // console.log('ID: ' + profile.getId());
          // console.log('Name: ' + profile.getName());
          // console.log('Image URL: ' + profile.getImageUrl());
          // console.log('Email: ' + profile.getEmail());

          this.userDetails.setLoginUser(new User({
            id: profile.getId(),
            name: profile.getName(),
            email: profile.getEmail()
          }));
        },
        (error) => {
          alert(JSON.stringify(error, undefined, 2));
        });
    });
  }
}

用户详情服务:

import {Injectable, OnInit} from '@angular/core';
import {User} from '../shared/models/user';
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
import 'rxjs/add/operator/map';

@Injectable()
export class UserDetailsService implements OnInit {

  private userSubject = new BehaviorSubject<User>(new User());
  user$ = this.userSubject.asObservable();

  constructor() {
  }

  ngOnInit(): void {
  }

  public setLoginUser(user: User) {
    this.userSubject.next(user);
  }
}

这是我的 UI 代码:

<div *ngIf="user" class="alert alert-success">{{user.name}}</div>
{{user.name}}

我错过了什么?现在已经坚持了一天多了。

感谢任何帮助,提前致谢。

最佳答案

发现问题。当我使用 setLoginUser 函数更新服务时,我这样做了:

this.userDetails.setLoginUser(new User({
              id: profile.getId(),
              name: profile.getName(),
              email: profile.getEmail()
            }));

我需要这样做:

this._zone.run(() =>{
            this.userDetails.setLoginUser(new User({
              id: profile.getId(),
              name: profile.getName(),
              email: profile.getEmail()
            }));
          });

现在两种方式都有效:

<div *ngIf="user" class="alert alert-success">{{user.name}}</div>
{{(userDetails.user$ | async).name}}

谢谢大家的帮助!

关于Angular 4 UI 未从可观察订阅更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47018864/

相关文章:

web-services - Angular 2 View 不显示来自 Web 服务的数据

html - 我如何验证智能表(ng2-smart-table)上的输入?

typescript - Angular 2 将复杂的服务注入(inject)到服务中

angular - HostListener 适用于 ngModel,但不适用于 FormControl

javascript - 如何在 Angular 4 中设置表单值?

angular - 强制多个组件使用同一个服务实例

Angular2 - 在哪里可以使用 InMemoryWebApiModule 配置端点?

angular - 使用 NTLM 身份验证的 ng serve --proxy-config 不起作用

Angular 4 : How to inject directives declared in bootstrapped module(appmodule) in other modules that are imported in the appmodule?

javascript - 显示小数点后 2 位数字的最佳实践