【问题标题】:ngFor is not showing any datangFor 没有显示任何数据
【发布时间】:2019-02-21 10:38:22
【问题描述】:

我正在尝试使用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 来填充数据库中的选择字段...。 删除该请求后,我的代码工作正常。

【问题讨论】:

  • 嗯,由于this.ItemToEdit = data 执行得稍晚一点,能否请您添加一个isLoading = false,在`this.ItemToEdit = data` 之后将其设置为true,并添加一个带有ngIf 的div在 ngFor 之外?
  • 可能在调用httpClienturl的值不正确。尝试在route.params.subscribe 回调中移动ngOnInit 的最后两条语句。
  • @ConnorsFan 没用
  • 在您订阅 httpClient 时,您将数据定义为 Array&lt;any&gt;。这和this.ItemToEdit = data; 行使ItemToEdit?.results 的访问无效,因为ItemToEdit 本身就是一个数组。如果您发现 itemToEdit 只有一个元素(这就是您要查找的内容),请在模板中更改对 ItemToEdit[0].results 的访问权限,在打字稿代码中更改对 ItemToEdit[0].results[0].name 的访问权限。
  • 只需将 html let item of ItemToEdit?.results 替换为 let item of ItemToEdit。并将 ts this.ItemToEdit = data; 替换为 this.ItemToEdit = data ? data.results : []

标签: html angular


【解决方案1】:

您现有的ngOnInit 方法有问题:

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

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

  1. 等到检索到 ID 后再发出 HTTP 请求,
  2. 仅当this.ItemToEdit 中有数据时才更新this.id,并且
  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;
    });
}

&lt;pre&gt;{{ ItemToEdit | json }}&lt;/pre&gt; 放置在模板中的某处可让您检查服务器的实际输出,从而识别来自服务器的常见错误。

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

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

<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>

【讨论】:

  • 感谢您的回答,我很感激,我试过了,我仍然得到同样的东西,空白 div
  • 考虑将&lt;pre&gt;{{ ItemToEdit | json }}&lt;/pre&gt; 放在模板中的某个位置,以准确识别返回的数据是否存在问题或其他问题。
  • 这是我得到的:{ "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 ......" }
  • 这很糟糕,但也很好。 很糟糕,因为您的服务器存在某种需要修复的问题,但很好,因为这意味着您的代码不会导致问题。您需要与管理服务器的人交谈,向他们发送该信息。
  • 我是管理这个 API REST 的人……我应该去别的地方看看……谢谢
【解决方案2】:

尽量让你的所有进程保持异步

<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'])
        );
    });
}

【讨论】:

  • 它给出了 TypeError: "_this.httpClient.get(...).map is not a function
  • 是的,我忘记了管道,也许您需要从 rxjs 添加地图运算符,
  • 这样 import { map } from 'rxjs/operators';
  • 在 chrome 的网络面板中检查您的 api 的返回。如果您没有错误,那可能是因为您没有检索数据。
  • ...但是你得到数据了吗?它的格式是否像地图运算符中的 data['results'] 一样返回
【解决方案3】:
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);
}

【讨论】:

  • 这在控制台中给了我:ERROR in src/app/item.component.ts(63,43): error TS2339: Property 'results' does not exist on type 'any[]'.
【解决方案4】:

首选的解决方案是使用 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();
  });
}

【讨论】:

  • 我试过了,但我不断收到 mysql 异常:命令不同步
  • 在服务中你是缓存数据库连接,还是打开一个新的?
  • 我从烧瓶 API REST 中获取数据。我有一个连接和一个会话,每次提交后我都会关闭,如果有任何异常则回滚。我在每项服务中都使用 try cach。请问我回答你的问题了吗?
  • 我不熟悉 Flask API REST 框架,所以对此我无能为力,但有证据表明该服务没有正确处理多个请求。最终,您需要先解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-15
  • 2017-02-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-28
相关资源
最近更新 更多