ngFor没有显示任何数据

时间:2018-09-17 13:25:27

标签: html angular

我正在尝试使用Angular 6将一些数据绑定到模板,所以这是ngOnInit

ngOnInit() {
    this.sub = this.route.params.subscribe(params => {
        this.id = +params['id'];
    });
    let url = this.baseUrl + `/items/${this.id}`;
    this.httpClient.get(url).subscribe((data : Array<any>)=> {
        this.ItemToEdit = data;
    });
}

这是模板:

<div *ngFor="let item of ItemToEdit?.results">
              <div class="col-sm-8 float-left">

                <mat-form-field> <input matInput
                  class="form-control" placeholder="Item name"
                  formControlName="name" id="ItemName" value='{{ item.name }}'>
                </mat-form-field>

              </div>
</div>

变量ItemToEdit如下:

{
  "results": [
    {
      "alias": [
        "first"
      ], 
      "apps": [], 
      "description": "this is an item", 
      "id": 1, 
      "name": "item342"
    }
  ]
}

因此,问题是当我打开模板(通过某个按钮)时,具有ngFor指令的HTML不显示(具有ngFor的div变为空白)。我不知道如何显示数据...变量ItemToEdit只有一个值(长度= 1),但是由于它有一个名为results的嵌套数组,因此我通过for循环显示数据。当我尝试在打字稿中执行以下操作时:

  this.loadedName = this.ItemToEdit.results[0].name;

我收到一条错误消息,说ItemToEdit.results未定义

有什么想法吗?

编辑

发现我的代码有效,但只有在刷新页面后...

服务器间歇性地返回这样的响应,而不是预期的结果:

  • { "error": "(_mysql_exceptions.OperationalError) (2006, 'MySQL server has gone away') [SQL: 'SELECT .... }
  • { "error": "(_mysql_exceptions.ProgrammingError) (2014, \"Commands out of sync; you can't run this command now\") [SQL: 'SELECT ......" }

================编辑2 ==============

我正在获取Mysql异常,因为我正在ngOnInit内进行另一个httpRequest来填充数据库中的选择字段...。 删除该请求后,我的代码可以正常工作。

4 个答案:

答案 0 :(得分:0)

尝试使所有进程保持异步

<div *ngFor="let item of (itemToEdit$ | async)">
    <div class="col-sm-8 float-left">

    <mat-form-field> <input matInput
      class="form-control" placeholder="Item name"
      formControlName="name" id="ItemName" value='{{ item.name }}'>
    </mat-form-field>

    </div>
</div>

在您的组件中:

private itemToEdit$: Observable<any>;

....

ngOnInit() {
    this.route.params.subscribe(params => {
        this.id = +params['id'];
        let url = this.baseUrl + `/items/${this.id}`;
        this.itemToEdit$ = this.httpClient.get(url).pipe(
          map(data => data['results'])
        );
    });
}

答案 1 :(得分:0)

test: any = [];  
ngOnInit() {
        this.service.test().subscribe(res => {
          this.test = res.results;
        });

HTML:

 <p *ngFor="let test of this.test">
   {{test.name}}
 </p>

如果您需要将其绑定到输入字段,只需为其分配:[value]="test?.name"

服务:

test(): Observable<any>{
return this.http.get(url);
}

答案 2 :(得分:0)

您现有的ngOnInit方法存在问题:

  1. this.id有机会被设置之前,它会读取this.id
  2. this.ItemToEdit发生更改时,它不会更新this.id
  3. this.id可能与当前加载的数据的实际ID不符。

以下建议的实现方案通过以下方式解决了这些问题:

  1. 在发出HTTP请求之前一直等到ID检索完毕,
  2. 仅在this.id中有可用数据时更新this.ItemToEdit,并且
  3. 如果ID在完成之前发生更改,则可以取消任何待处理的HTTP请求。
ngOnInit() {
    let itemToEditID;
    const httpObservable = this.route.params.pipe(
        map(params => +params['id']),
        tap(newID => itemToEditID = newID),
        switchMap(newID => this.httpClient.get(`${this.baseUrl}/items/${newID}`))
    );
    this.sub = httpObservable.subscribe(data => {
        this.id = itemToEditID;
        this.ItemToEdit = data;
    });
}

<pre>{{ ItemToEdit | json }}</pre>放在模板中的某个位置使您可以检查服务器的实际输出,从而可以确定来自服务器的常见错误。

有关这些错误的好消息是它们是由服务器而不是您的代码引起的。坏消息是,您需要确定服务器出了什么问题以及如何解决该问题,但这是另一个问题的话题。

根据您的需要,您可能希望在发生以下情况时在页面上输出服务器错误:

<div *ngIf="ItemToEdit?.error" class="danger">
    <h2>An error occurred while trying to retrieve item {{ id }}</h2>
    <p>{{ error }}</p>
</div>
<div *ngFor="let item of ItemToEdit?.results">
    <!-- ... -->
</div>

答案 3 :(得分:0)

首选解决方案是使用 antoine-clavijo 答案中定义的async

或者,如果您的组件(或父组件)是使用ChangeDetectionStrategy.OnPush定义的,例如:

@Component({
  selector: 'app-component',
  templateUrl: './config.component.html',
  changeDetection: ChangeDetectionStrategy.OnPush
})

...您可以告诉Angular需要更新组件,如下所示:

constructor(
  private ref: ChangeDetectorRef, 
  private httpClient: HttpClient) {}

ngOnInit() {
  this.sub = this.route.params.subscribe(params => {
    this.id = +params['id'];
  });
  const url = this.baseUrl + `/items/${this.id}`;
  this.httpClient.get(url).subscribe((data: Array<any>)=> {
    this.ItemToEdit = data;
    this.ref.detectChanges();
  });
}