angular2 ngFor 在 ngOnInit() 上从 api 获取数据时不工作

angular2 ngFor not working while fetching data from api on ngOnInit()

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 在响应之前呈现。但是在刷新页面时数据会自动绑定。我错过了什么吗?

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

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

所以一旦 comments 被加载,Angular 将强制刷新,并且 ul 将被添加到 DOM,此时它将具有每个评论绑定 li 所需的所有数据。

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

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

尝试在 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

返回数据

试试这个
模板:<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

中达到订阅,这些值就未定义
 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.    

Is this a correct way to bind data with HTML if data is coming using api?

    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();
        }

    }

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

private cdr: ChangeDetectorRef

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

this.cdr.detectChanges();

我对 angular2 有同样的问题,从 OnInit/AfterViewInit 调用 API 并且绑定没有在视图中更新(select 下拉数组没有填充在视图中)。 上述方法对我有用,但我仍然不知道根本原因。

Please direct me to the root cause for this issue as I am unable to find one.

Tt 现在是 2022 年了,问题仍然存在 angular 6. 另一种解决方法是使用 setTimeout 函数,它会进行脏检查。

ngOnInit() {
   setTimeout(() => {
        this.comments = this.getComments();
   }, 1000);       
}