来自Express Subscribe调用的JSON数组的Angular HTML绑定错误

时间:2018-05-03 13:57:10

标签: javascript html arrays json angular

我目前的设置就是这个。

    我的ngOnInIt
  1. dashboard.component.ts运行了databaseService来订阅结果。

  2. database.service.ts运行http POST获取数据并填充值IssuerGroup

  3. 我想显示我的数据库以HTML格式提供给我的JSON的结果。

  4. 以下代码:

    dashboard.component.ts

    import { IssuerGroup } from './../database.service';
    import { Component, OnInit } from '@angular/core';
    import { RouterLink } from '@angular/router';
    import { FormArray, FormControl, FormGroup, Validators } from '@angular/forms';
    import { Observable } from 'rxjs/Observable';
    import { HttpClient } from '@angular/common/http';
    import { element } from 'protractor';
    import { ActivatedRoute } from '@angular/router';
    import { DatabaseService } from '../database.service';
    
    @Component({
      selector: 'app-dashboard',
      templateUrl: './dashboard.component.html',
      styleUrls: ['./dashboard.component.css']
    })
    export class DashboardComponent implements OnInit {
    
      issuerGroups: IssuerGroup[];
    
      constructor(
        private databaseService: DatabaseService,
        private route: ActivatedRoute
      ) {}
    
      ngOnInit() {
        const id = this.route.snapshot.paramMap.get('id');
        this.databaseService.getGroup(id)
          .subscribe(issuerGroups => this.issuerGroups = issuerGroups);
      }
    }
    

    database.service.ts

    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { Observable } from 'rxjs/Observable';
    import { map } from 'rxjs/operators';
    import 'rxjs/add/operator/catch';
    import 'rxjs/add/observable/throw';
    import 'rxjs/add/operator/do';
    import 'rxjs/add/operator/toPromise';
    
    export class IssuerGroup {
      Issuer_Id: number;
      Issuer_Name: string;
      Issuer_Group_Name: string;
    }
    @Injectable()
    export class TeradataService {
      constructor(private _http: HttpClient) {}
    
      getGroup(id): Observable<IssuerGroup[]> {
        const url = 'http://localhost:3000/ig';
        const data = ({
          issuerid: id
        });
        return this._http.post(url, data)
        .pipe(
          map((res) => {
            console.log(res);
            return <IssuerGroup[]> res;
          })
        );
      }
    }
    

    dashboard.component.html

    <p> Display the Issuer Name here: {{ issuerGroups.Issuer_Name }} </p>
    
    <!-- ERROR TypeError: Cannot read property 'Issuer_Name' of undefined -->
    
    <p> Display the Issuer Name here: {{ issuerGroup.Issuer_Name }} </p>
    
    <!-- ERROR TypeError: Cannot read property 'Issuer_Name' of undefined -->
    
    <p> Display the Issuer Name here: {{ issuerGroups[0].Issuer_Name }} </p>
    
    <!-- this last result produces the following error but the data actually displays on screen correctly -->
    
    <!-- ERROR TypeError: Cannot read property '0' of undefined -->
    

    在HTML页面的最后一个示例中,数据显示但仍然收到错误。

    目标:显示我在HTML页面中从数据库返回的JSON的结果,没有错误。任何帮助将不胜感激。

2 个答案:

答案 0 :(得分:1)

您可以在将变量绑定到HTML模板时使用the safe navigation operator(属性前为?),如:

{{ issuerGroups?.Issuer_Name }}

只有当 Issuer_Name存在(不是issuerGroupsnull)时,全局才会显示undefined 。优点是您不必使用*ngIf(某些情况除外)或进一步检查属性是否存在以将其显示在视图中。

因此,在您的示例中,它将如下所示:

<p> Display the Issuer Name here: {{ issuerGroup?.Issuer_Name }} </p>

但是,在你的最后一个绑定中,既然你正在调用一个索引,我建议你这样做:

<p *ngIf="issuerGroups?.length"> Display the Issuer Name here: {{ issuerGroups[0]?.Issuer_Name }} </p>

或者那样:

<p> Display the Issuer Name here: {{ issuerGroups?.length ? issuerGroups[0]?.Issuer_Name : '' }} </p>

但是有很多方法可以做到这一点。

答案 1 :(得分:1)

问题是您在模板属性中使用可能尚不存在的属性。解释你的错误:

<p> Display the Issuer Name here: {{ issuerGroups.Issuer_Name }} </p>

这会失败,因为在数据加载之前,issuerGroups变量未初始化为任何对象值,并且您显然无法读取undefined的属性。加载数据后,它不会失败,但它也不会显示任何内容,因为issuerGroups被设置为数组类型,该类型没有Issuer_Name字段。

<p> Display the Issuer Name here: {{ issuerGroup.Issuer_Name }} </p>

这将始终失败,因为您的组件根本没有定义issuerGroup字段。

<p> Display the Issuer Name here: {{ issuerGroups[0].Issuer_Name }} </p>

这在数据加载之前失败,因为数组没有初始化,即使你用[]初始化它也没有任何元素,因此你不能在0索引处读取条目,直到存在那里有一个。

你应该做的是:

<p> Display the Issuer Name here: {{ getIssuerName() }} </p>

在控制器中添加方法:

getIssuerName() {
    if (this.issuerGroups && this.issuerGroups.length > 0) {
        return this.issuerGroups.Issuer_Name[0];
    } else {
        return "";
    }
}

(当然,您可以在HTML文件中进行内联检查,就像其他人建议的那样,该方法仅用于代码可读性)

TL; DR:
当它们尚未加载时,不要访问异步加载的对象的成员。