简体   繁体   English

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

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

comment.component.ts: 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 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;
            });
        }
    }

Within ngOnInit method I am able to get list of comments but the problem is the list is not binding using ngFor on the HTML. ngOnInit方法中,我能够获得注释列表,但问题是列表没有使用HTML上的ngFor绑定。 This is because HTML is rendering before the response. 这是因为HTML在响应之前呈现。 But On refreshing page data binds automatically. 但是刷新页面数据会自动绑定。 Am I missing something? 我错过了什么吗?

One solution would be to only display your ul once your comments have been loaded, which would then force a refresh. 一种解决方案是只在您的注释被加载后才显示您的ul ,然后强制刷新。 So something like: 所以类似于:

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

So once comments has been loaded, Angular will force a refresh, and the ul will be added to the DOM, at which point it will have all the data it needs to bind an li per comment. 因此,一旦加载了comments ,Angular将强制刷新,并且ul将被添加到DOM,此时它将具有绑定每个注释的li所需的所有数据。

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

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

You can use ChangeDetectorRef class to forcefully detect changes for a component and it's child components. 您可以使用ChangeDetectorRef类强制检测组件及其子组件的更改。 You will need to create class property of type ChangeDetectorRef like following: 您需要创建类型为ChangeDetectorRef的类属性,如下所示:

private cdr: ChangeDetectorRef

After you load data in OnInit(), just call detectChanges() method to manually run change detection: 在OnInit()中加载数据后,只需调用detectChanges()方法手动运行更改检测:

this.cdr.detectChanges();

I am having same issue with angular2, calling API from OnInit/AfterViewInit and bindings are not updated in view (select dropdown array not populated inside view). 我对angular2有同样的问题,从OnInit / AfterViewInit调用API并且视图中没有更新绑定(选择下拉数组未在视图中填充)。 Above approach worked for me, but root cause is still unknown to me. 以上方法对我有用,但根本原因对我来说仍然是未知的。

Please direct me to the root cause for this issue as I am unable to find one. 请指导我找到这个问题的根本原因,因为我无法找到。

Try adding the ngFor in the ul tag 尝试在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>`

also maybe you have not pasted your entire code, i don't see a injection of the service component. 也许你还没有粘贴整个代码,我没有注意到服务组件的注入。

you will need to import and inject the service in the component that you want to use it in. In the component constructor 您将需要在要使用它的组件中导入和注入服务。在组件构造函数中

    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

Hopefully you have tested that your commentService is returning data via console.log 希望您已经测试过您的commentService通过console.log返回数据

Try this 试试这个
template: <ul><li *ngFor="let comment of comments|async"> {{comment.Name}}</li></ul> 模板: <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();   
   }

I see 2 problems in your code 1. You call map without returning any value. 我在你的代码中看到了2个问题1.你调用map而不返回任何值。 2. You try to set values inside map instead of subscribe but the values was undefined once it reach subscribe in your ngOnInit 2.您尝试在map中设置值而不是subscribe,但是一旦在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? 如果数据来自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();
        }

    }

Here is how I solved the issue: 以下是我解决问题的方法:

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

You shouldn't use this.classroom though, it should be: 你不应该使用this.classroom ,它应该是:

this.comments = data | [];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM