1

在我的项目中,我通过 Google Contact API 获取电子邮件。我的问题是在获取电子邮件后,角度 UI 没有更新。

这是我在 ContactComponent.ts 中获取电子邮件的代码

import { Component, OnInit, EventEmitter, Output, ViewChild } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { ContactService } from './contacts.service';
import { Contact } from './contact.model';
import { Subject } from 'rxjs';
import { ContactListComponent } from './contact-list/contact-list.component';
declare var gapi: any;

@Component({
  selector: 'app-contacts',
  templateUrl: './contacts.component.html',
  styleUrls: ['./contacts.component.css'],
  providers: [ContactService]
})
export class ContactsComponent implements OnInit {
  constructor(private http: HttpClient, private contactService: ContactService) {}
  authConfig: any;
  contactsList: Contact[] = [];
  ContactsFound = true;
  ngOnInit() {

    this.ContactsFound = false;

    this.authConfig = {
      client_id:
        '<my_client_id>',
      scope: 'https://www.googleapis.com/auth/contacts.readonly'
    };

  }

  fetchGoogleContacts() {
    gapi.client.setApiKey('<my_key>');
    gapi.auth2.authorize(this.authConfig, this.handleAuthorization);
  }

  handleAuthorization = authorizationResult => {
    if (authorizationResult && !authorizationResult.error) {
      const url: string =
        'https://www.google.com/m8/feeds/contacts/default/thin?' +
        'alt=json&max-results=500&v=3.0&access_token=' +
        authorizationResult.access_token;
      console.log('Authorization success, URL: ', url);
      this.http.get<any>(url).subscribe(response => {
        if (response.feed && response.feed.entry) {
          // console.log(response.feed.entry);
          this.saveContacts(response.feed.entry);
        }
      });
    }
  }

  saveContacts(ContactEntry) {

    this.contactsList = [];

    ContactEntry.forEach((entry) => {
      // tslint:disable-next-line:prefer-const
      let contact: Contact = { email: '', name: '' };

      if (entry.gd$name !== undefined) {
        contact.name = entry.gd$name.gd$fullName.$t;
        // console.log('Name of contact: ' + contact.name);
      }

      if (Array.isArray(entry.gd$email)) {
        entry.gd$email.forEach((emailEntry) => {
          if (emailEntry.address !== undefined) {
           // console.log('Email of contact: ' + emailEntry.address);
            contact.email = emailEntry.address;
          }
        });
      }

      this.contactsList.push(contact);
    });

    this.ContactsFound = true;
     // Calling next in ContactService for propagating the events
    this.contactService.contactsArrived(this.contactsList);
    console.log(`Contacts List Length ${this.contactsList.length}`);

  }



} 

我正在使用服务订阅事件以添加电子邮件

import { Injectable } from '@angular/core';
import { Contact } from './contact.model';
import {  BehaviorSubject, Subject } from 'rxjs';
import { TouchSequence } from 'selenium-webdriver';



@Injectable()
export class ContactService {
  contacts: Contact[] = [];
  private contactsSubject = new Subject<Contact[]>();
  contactArrived$ = this.contactsSubject.asObservable();

  constructor() {
  }

  contactsArrived(contacts: Contact[]) {
     console.log(`Contacts Arrived in Contact Service`);
     if (contacts) {
        this.contactsSubject.next(contacts);
     }
  }
}

这是我的contact.component.html

<button class="btn btn-primary" (click)="fetchGoogleContacts()">Import Contacts</button>
<app-contact-list [contacts]="contactsList"></app-contact-list>

联系人列表组件的代码

import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
import { ContactService } from '../contacts.service';

import { Contact } from '../contact.model';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-contact-list',
  templateUrl: './contact-list.component.html',
  styleUrls: ['./contact-list.component.css']
})
export class ContactListComponent implements OnInit, OnDestroy {
  @Input() contacts: Contact[];
  subscription: Subscription;

  constructor(private contactService: ContactService) {
  }

  ngOnInit() {
    this.subscription = this.contactService.contactArrived$.subscribe(data => {
      console.log(data);
      this.contacts = data;
    });
  }

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


}

联系人列表组件.html

<div>
  <div>
    <br>
    <h4 class="card-title">Your Contacts</h4>
    <div class="card">
      <div class="card-header">Contact Names
        <span class="float-right">Emails Ids</span>
      </div>
      <ul *ngFor="let contact of contacts" class="list-group list-group-flush">
        <app-contact-item [contact]="contact"></app-contact-item>
      </ul>
    </div>
  </div>
</div>

在来自谷歌联系人 API 的其余调用之后,我在联系人列表组件中获取数据。但是总结一下我的用户界面没有更新。列表未更新。谷歌搜索后,我了解到 Angular 对 ngZone 之外的事件的行为有所不同。收到数据后如何更新 UI。

4

1 回答 1

-1

根本原因

看起来它contacts没有被捕获为 Angular 的变更检测器机制的一部分。

修复:你有几个选择

首先是有 setter 和 gettercontacts

Functions作为变更检测器的一部分,它始终扮演着至关重要的角色,因此它可以确保变更生效并相应地更新 UI。

在 ts

import { Component, OnInit, Input, OnDestroy, OnChanges, SimpleChanges } from '@angular/core';
import { ContactService } from '../contacts.service';

import { Contact } from '../contact.model';
import { Subscription } from 'rxjs';

@Component({
  selector: 'app-contact-list',
  templateUrl: './contact-list.component.html',
  styleUrls: ['./contact-list.component.css']
})
export class ContactListComponent implements OnInit, OnDestroy {
  @Input("contacts") _contacts: Contact[];
  subscription: Subscription;

  constructor(private contactService: ContactService) {
  }

  ngOnInit() {
    this.subscription = this.contactService.contactArrived$.subscribe(data => {
      console.log(data);
      this._contacts = data;
    });
  }

    get contacts(){
        return this._contacts;
    }

    set contacts(contacts){
        this._contacts = contacts;
    }

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

}

设置联系人时使用 setTimeout 的第二个选项

ngOnInit() {
        this.subscription = this.contactService.contactArrived$.subscribe(data => {
          console.log(data);
          setTimeout(()=>this.contacts = data);
        });
      }
于 2018-10-20T17:51:47.700 回答