Ошибка углового связывания HTML с массивом JSON из вызова Express Subscribe - PullRequest
0 голосов
/ 03 мая 2018

Моя текущая настройка такова.

  1. ngOnInIt для моего dashboard.component.ts запускает вызов databaseService, чтобы подписаться на результат.

  2. database.service.ts запустить http POST, чтобы получить данные и заполнить значение IssuerGroup.

  3. Я хочу отобразить результат JSON, данный мне моей базой данных в HTML.

код ниже:

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 отображаются данные, но все равно появляется ошибка.

Цель: Показать результат JSON, который я получил из базы данных, на моей HTML-странице без ошибок. Любая помощь будет принята с благодарностью.

Ответы [ 2 ]

0 голосов
/ 03 мая 2018

Проблема в том, что вы используете в своем шаблоне свойства, которые могут еще не существовать. Объясняя свои ошибки:

<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:
Не обращаться к членам объектов, загруженных асинхронно, когда они еще не загружены.

0 голосов
/ 03 мая 2018

Вы можете использовать the safe navigation operator (со свойством ? перед) при привязке переменных к вашему HTML-шаблону, например:

{{ issuerGroups?.Issuer_Name }}

По вашему мнению, глобально выводится Issuer_Name , только если существует issuerGroups (не null или 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>

Но есть так много способов сделать это.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...