2

我进行异步服务调用以获取元素列表。

 public elementList: Array<Element>;
   ... 
   this.service.getElementList().subscribe( list => {
       this.elementList = list;
       this.createFormGroup(list);
     }
   );
   ...

当我收到元素列表(我订阅了服务调用)时,我根据元素列表构建表单组。在模板中,我有一个 *ngIf 来绘制仅当列表大于零时。

*ngIf="elementList?.length>0"

由于 elementList 是异步获取的,所以这个 ngIf 不起作用。我读过我可以将 ngIf 与 AsnycPipe 一起使用。所以在模板中我会有:

*ngIf="elementList$ && elementList$.length>0"

其中 elementList$ 是服务调用返回的 Observable。

   public elementList$: Observable<Array<Element>>;   

   elementList$ =this.service.getElementList()

我想知道收到 elementList 后如何创建 FormGroup。首先我需要创建 FormGroup,然后模板应该调用 *ngIf 来绘制元素。

4

3 回答 3

2

可以有许多不同的方法来做到这一点。我现在只分享两种方法,如果您觉得这些方法中的任何一种都不能满足您的用例,我们可以考虑另一种方法(前提是您提供更多关于您在此处尝试实现的目标的信息) .

方法一:

您的组件上有两个属性:

form$: Observable<FormGroup>;
list: Array<Element>;

一旦你有了 API 响应,而不是subscribeing 到它,你map它并生成一个表单,同时还将响应的值分配给list你声明的属性。像这样的东西:

this.form$ = this.service.getElements()
  .pipe(
    map((list: Array<Element>) => {
      this.list = list;
      return this.fb.group({
        elementId: [list[0].id],
        elementDescription: [list[0].description]
      });
    })
  );

然后在模板中使用它,有点像这样:

<form 
  *ngIf="form$ | async as form"
  [formGroup]="form">
  <label for="">Element Id: </label>
  <select formControlName="elementId">
    <option 
      *ngFor="let element of list"
      [value]="element.id">
      {{ element.id }}
    </option>
  </select>
  <br>
  <label for="">Element description: </label>
  <select formControlName="elementDescription">
    <option 
      *ngFor="let element of list"
      [value]="element.description">
      {{ element.description }}
    </option>
  </select>
</form>

方法二:

您可能希望将列表和列表FormGroup合并在一起。因此,您可以在组件中创建单个属性:

elementListWithForm$: Observable<{ list: Array<Element>, form: FormGroup }>;

然后你会分配一个像这样的值:

this.elementListWithForm$ = this.service.getElements()
  .pipe(
    map((list: Array<Element>) => ({ 
      form: this.fb.group({
        elementId: [list[0].id],
        elementDescription: [list[0].description]
      }),
      list,
     }))
  );

然后你可以像这样在模板中使用它:

<form 
  *ngIf="(elementListWithForm$ | async) as formWithList"
  [formGroup]="formWithList.form">
  <label for="">Element Id: </label>
  <select formControlName="elementId">
    <option 
      *ngFor="let element of formWithList.list"
      [value]="element.id">
      {{ element.id }}
    </option>
  </select>
  <br>
  <label for="">Element description: </label>
  <select formControlName="elementDescription">
    <option 
      *ngFor="let element of formWithList.list"
      [value]="element.description">
      {{ element.description }}
    </option>
  </select>
</form>

这是StackBlitz 上的工作代码示例,供您参考。

PS:这种方法很大程度上受到了我在一篇文章中使用的方法的启发,那篇文章是关于在 Angular 中为 AngularInDepth 提高深度嵌套的响应式表单的性能。您可能也想检查一下。

希望这可以帮助。:)

于 2019-12-10T10:18:56.503 回答
2

根据@SiddAjmera 的回答,我构建了满足我需求的第三个选项。

方法3:

formGroup: FormGroup;
elementList$: Observable<Array<Element>>;

一旦我得到 API 响应:

    this.elementList$ = this.service.getElements()
    .pipe(
        map((list: Array<Element>) => {
            this.formGroup = this.fb.group({
                elementId:          [list[0].id],
                elementDescription: [list[0].description]
            });
            return list;
        })
    );

然后在模板中我有这个:

    <form
      *ngIf="(elementList$ | async) as list"
            [formGroup]="formGroup"  (ngSubmit)="onSubmit()">
      <label for=''>Element Id: </label>
      <select formControlName="elementId">
        <option
                *ngFor="let element of list"
                [value]="element.id">
          {{ element.id }}
        </option>
      </select>
      <br>
      <label for=''>Element description: </label>
      <select formControlName="elementDescription">
        <option
                *ngFor="let element of list"
                [value]="element.description">
          {{ element.description }}
        </option>
      </select>  
      <br>
      <button type="submit">Click</button
</form>

在组件中,当我单击按钮时,我访问表单组以获取值:

public onSubmit() {
    console.log(this.formGroup.toString());
}
于 2019-12-10T15:17:09.213 回答
0

首先(但只是挑剔),我相信“绘画”元素的正确术语是“渲染”元素。(老实说,我对你使用的术语没意见。)

关于问题本身,您可以通过管道将Observable列表通过管道来async检查列表的长度,然后检查该管道列表的长度:

*ngIf="elementList$ && (elementList$ | async)?.length > 0"
于 2019-12-09T12:48:55.033 回答