【问题标题】:Angular Reactive Form Array with Radio Buttons带有单选按钮的 Angular 反应表单数组
【发布时间】:2019-11-02 15:02:29
【问题描述】:

我遇到了反应式表单和单选按钮数组的问题。

我的表单如下所示:


连续有一个玩家,我必须选择状态。

组件:

 <tr *ngFor="let data of player">
        <th>{{data.firstname}} {{data.lastname}}</th>
        <th *ngFor="let stat of status">
        <input type="radio" id="opt1+{{data.id}}" value="{{stat}}" name="option+{{data.id}}" formArrayName="status???"></th>
      </tr>

玩家数据来自API,状态为数组。

ts:

this.myForm = formBuilder.group({
    status: this.formBuilder.array,
    })

我的例子不起作用。 结果我需要一个 json 文件。 (玩家姓名 + 状态,例如在场) 我找不到实现它的方法。 有什么提示吗?

【问题讨论】:

  • 汉斯,您没有FormArray,您的表单只有两个字段:playerName 和status(而status 可以是以下值之一:·出席、失踪、道歉和无故)。您使用数组来显示单选按钮,但您只有一个 formName
  • 我想每行都需要一个额外的名称。正确的?但我不知道该怎么做。
  • 抱歉,我没看出你想控制所有玩家。

标签: angular angular-reactive-forms angular-formbuilder


【解决方案1】:

也许你可以不使用表格来做到这一点。

基本上有一个这样的html设置,使用ngModel来设置状态:

<table>
  <tr>
    <th>Firstname</th>
    <th>present</th>
    <th>missing</th>
    <th>apologizes</th>
    <th>unexcused</th>
  </tr>
  <tr *ngFor="let data of player">
    <th>{{data.firstname}} {{data.lastname}}</th>
    <th *ngFor="let stat of status">
      <input type="radio" id="opt1+{{data.id}}" [(ngModel)]="data.status" value="{{stat}}" name="option+{{data.id}}">
    </th>
  </tr>
</table>

还有一个获取所需数据的简单函数:

  getJsonResult() {
    alert(JSON.stringify(this.player.map(x => {
      return {
        playername: x.firstname + ' ' + x.lastname,
        status: x.status
      }
    })));
  }

stackblitz 上的工作示例。

更新

ReactiveForm 方式需要更多代码。首先有一个 FormGroup,然后在一个带有玩家的 FormArray 内。 formArrayName="players"

<form (ngSubmit)="onSubmit()" [formGroup]="playersForm">
  <table border="1">
    <tr>
      <th>Firstname</th>
      <th>present</th>
      <th>missing</th>
      <th>apologizes</th>
      <th>unexcused</th>
    </tr>
    <tr formArrayName="players" *ngFor="let data of playersForm.get('players').controls; let i = index">
      <ng-container [formGroupName]="i">
        <th>
          <input type="text" formControlName="name" readonly>
        </th>
        <th *ngFor="let stat of status">
          <input type="radio" formControlName="status" value="{{stat}}">
        </th>
      </ng-container>
    </tr>
  </table>
  <br>
  <button type="submit">Submit</button>
</form>

Typescript 部分将构建并填充数组。

playersForm: FormGroup; constructor(private fb: FormBuilder) { }

  ngOnInit(): void {
    this.playersForm = this.fb.group({
      players: this.fb.array([])
    });

    this.player.forEach(p => {
      (this.playersForm.get('players') as FormArray).push(
        this.addPlayerFormGroup(p.firstname + ' ' + p.lastname, '')
      );
    });
  }

  private addPlayerFormGroup(name?: string, status?: string): FormGroup {
    return this.fb.group({
      name,
      status
    });
  }

  onSubmit() {
    alert(JSON.stringify(this.playersForm.value));
  }

在 app.moudule.ts 中 import { ReactiveFormsModule } from '@angular/forms'; 而不是 FormsModule。

新工作stackblitz

第二次更新

正如@Eliseo 建议的那样,您可以在不嵌套 FormArray 的情况下做到这一点。

  ngOnInit(): void {
    this.playersForm = this.fb.array([]);

    this.player.forEach(p => {
      this.playersForm.push(
        this.addPlayerFormGroup(p.firstname + ' ' + p.lastname, '')
      );
    });
  }

html:

<tr *ngFor="let fg of playersForm.controls; index as i">        
<td>
  <input type="text" [formControl]="fg.get('name')" readonly>
</td>
<td *ngFor="let stat of status">

  <input type="radio" id="opt1+{{player[i].id}}" value="{{stat}}" name="option+{{player[i].id}}" 
    [formControl]="fg.get('status')">
</td>  

Stackblitz

第三次更新

如果您有来自 observable 的数据,请考虑以下方法。我正在使用 SWAPI 来获取一些数据。一旦你收到数据。您可以将原始数据映射到所需的格式,然后调用方法来填充 FormArray。

  ngOnInit(): void {
    this.playersForm = this.fb.array([]);
    let counter = 0;
    const apiUrl = 'https://swapi.co/api/people';    
    this.http.get(apiUrl).subscribe((peoples: any) => {
      this.player = peoples.results.map(p => {
        return {
          id: ++counter,
          name: p.name,
          staus: null
        }
      })
      this.populateForm();
    });
  }

  private populateForm() {
    this.player.forEach(p => {
      this.playersForm.push(
        this.addPlayerFormGroup(p.name, '')
      );
    });
  }

Stackblitz

【讨论】:

  • 我需要更多帮助。目前playersForm只有fb.array。如何添加更多字段?例如我需要一个团队名称和年份数据字段。 formBuilder.group 是一个选项吗?
  • @HansPeter 如果您在播放器旁边需要更多字段,请检查第一个更新,您有 this.playersForm = this.fb.group({... 作为该 formGroup 中的主要父组,您可以添加更多字段,包括播放器的表单数组等。
猜你喜欢
  • 1970-01-01
  • 2018-07-04
  • 1970-01-01
  • 1970-01-01
  • 2017-04-16
  • 2023-04-05
  • 1970-01-01
  • 2019-04-12
  • 2015-11-02
相关资源
最近更新 更多