angular2 ng在ngOnInit()从api获取数据时不起作用

时间:2017-03-16 03:23:03

标签: angular angular2-observables

comment.component.ts:

import { Component, OnInit } from '@angular/core';
import { Router} from '@angular/router'
import { Comment } from 'comment entity path'
import {CommentService} from 'comment service path'
import { Observable } from 'rxjs/Observable';
@Component({
    template: ` <ul><li *ngFor="let comment of comments|async"> {{comment.Name}}</li></ul>`
})
export class CommentComponent implements OnInit {
    comments: Observable<comment[]>;  

    constructor(private router: Router, private commentService: CommentService) {
    }

    ngOnInit() {
        this.comments = this.getComments();
    }

    getComments() {
        return this.commentService.getComments();
    }

}

comment.service.ts

import { Injectable } from '@angular/core';
import { Headers, Http, Response } from '@angular/http';
import { Comment } from 'comment path here';
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class CommentService {
    private commentUrl = 'api path';  // URL to web api

    constructor(private http: Http) {
    }

    getComments(): Observable<Comment[]> {
        return this.http.get(this.commentUrl).map(
            (response) => {
                let data = response.text() ? response.json():[{}];
                if (data) {
                    console.log(data);
                    return data;
                }
                return data;
            });
        }
    }

ngOnInit方法中,我能够获得评论列表,但问题是列表没有使用HTML上的ngFor进行绑定。这是因为HTML在响应之前呈现。但是刷新页面数据会自动绑定。我错过了什么吗?

7 个答案:

答案 0 :(得分:2)

一种解决方案是仅在您的评论加载后显示您的ul,然后强制刷新。如下所示:

<ul *ngIf="comments"><li *ngFor="let comment of comments">{{comment.Name}}</li></ul>

因此,一旦加载了comments,Angular将强制刷新,ul将被添加到DOM,此时它将拥有绑定{{{}所需的所有数据。每条评论1}}。

答案 1 :(得分:1)

使用异步管道通过observable加载数据。

<li *ngFor="let comment of comments | async">

答案 2 :(得分:1)

您可以使用 ChangeDetectorRef 类强制检测组件及其子组件的更改。 您需要创建类型为 ChangeDetectorRef 的类属性,如下所示:

private cdr: ChangeDetectorRef

在OnInit()中加载数据后,只需调用 detectChanges()方法手动运行更改检测:

this.cdr.detectChanges();

我遇到与angular2相同的问题,从OnInit / AfterViewInit调用API并且视图中没有更新绑定(选择下拉数组未在视图中填充)。 以上方法对我有用,但根本原因对我来说仍然是未知的。

  

请告诉我这个问题的根本原因,因为我找不到。

答案 3 :(得分:0)

尝试在ul标签中添加ngFor

<ul  *ngFor="let comment of comments"><li > {{comment.Name}}</li></ul>`

or

<ul  *ngFor="let comment of (comments|async)"> <li> {{comment.Name}}</li></ul>`

也许您还没有粘贴整个代码,我也没有注意到服务组件的注入。

您需要在要使用它的组件中导入和注入服务。 在组件构造函数

    import {CommentService} from '../path to service'

    constructor(private commentService: CommentService) 
    {

    //you can call the getcomments service here itself or in ngOnInit
    this.commentService.getComments().subscribe(data =>    
                 {    
                   console.log(data)
                  }
    } //end constructor

希望您已经测试过您的commentService通过console.log

返回数据

答案 4 :(得分:0)

试试这个 模板:<ul><li *ngFor="let comment of comments|async"> {{comment.Name}}</li></ul>

comments: Observable<comment[]>;  
    ngOnInit() {      
       this.comments = this.getComments();
    }

    getComments() {      
     return this.commentService.getComments();   
   }

我在你的代码中看到了2个问题 1.您调用map而不返回任何值。 2.您尝试在地图中设置值而不是订阅,但是一旦在您的ngOnInit中达到订阅,这些值就是未定义的

答案 5 :(得分:0)

 I have found a solution of my issue using Zone and promise.
 below is the update code of the "comments.component.ts".
 by using zone.run(), I am able to bind data with HTML when
 "comments.component" is loaded.    
  

如果数据来自api,这是用HTML绑定数据的正确方法吗?

    import { Component, OnInit, NgZone } from '@angular/core';  //NgZone *
    import { Router} from '@angular/router'
    import { Comment } from 'comment entity path'
    import {CommentService} from 'comment service path'
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/operator/toPromise'   // *
    @Component({
        template: `<ul  *ngIf="comments && comments.length > 0">
                   <li *ngFor="let item of comments"> {{item.Name}}</li>
                   </ul>`
    })
    export class CommentComponent implements OnInit {
        comments: comment[]=[];   // *

        constructor(private router: Router, private commentService: CommentService, private zone: NgZone) {
        }

        ngOnInit() {

          this.zone.run(() => {
            this.getComments().toPromise().then((data) => {
                this.comments= data || [];
            });
            })
         }

        getComments() {
            return this.commentService.getComments();
        }

    }

答案 6 :(得分:-1)

以下是我解决问题的方法:

//initialize the variable comment 
comments: comment[];  // this is given you have a comment model.

你不应该使用this.classroom,它应该是:

this.comments = data | [];