【问题标题】:ReactiveForm inside an NgForNgFor 中的响应式表单
【发布时间】:2019-02-22 12:51:02
【问题描述】:

我有一个 ngFor,它包含在一个响应式表单中。这是代码:

<div class="element-list">
        <form [formGroup]="formGroup" class="single-item" *ngFor="let p of points; let i = index">
            <span>Lat: </span> <input formControlName="lat" type="text" value="{{p.lat}}">
            <span>Lon: </span> <input formControlName="lon" type="text" value="{{p.lon}}">
            <a (click)="updateData(i)">Submit</a>
        </form>
    </div>

这是.ts的一面

export class MapInfoBarComponent implements OnInit, OnDestroy
{
  points: MapDetailModel[] = [];
  isAlive = true;
  formGroup: FormGroup;


  constructor(
    private mapService: MapService,
    private fb: FormBuilder
    ){}

  ngOnInit() {

    this.mapService.pointsChanged
    .takeWhile(() => this.isAlive)
    .subscribe( evt => {
      if(!!evt){
        this.points = evt;
      }
    });

    this.formGroup = this.fb.group({
      lat: new FormControl(),
      lon: new FormControl()
    });
  }


  ngOnDestroy(): void {
    this.isAlive = false;
  }

  updateData(id: number){
    console.log(id + " > " + this.formGroup.value);
  }
}

每当我点击a 时,我从this.formGroup.value 得到的只是空值和空值。

问题

我的问题是,当我点击一个按钮时,如何“知道”我指的是哪个 formGroup? this.points 有时会发生变化,从另一个组件推送新元素。

例如,我想更新第三个元素,并在console.log 中查看更新后的值。

感谢任何帮助。谢谢。

我是如何解决这个问题的

感谢 @ak.leimrey 将下面的链接传递给我。

我是这样解决的:

.ts 文件:

export class MapInfoBarComponent implements OnInit, OnDestroy
{
  points: MapDetailModel[] = [];
  isAlive = true;
  survey: FormGroup;
  items = false;

  constructor(
    private mapService: MapService,
    private fb: FormBuilder
    ){}

  ngOnInit() {



    this.mapService.pointsChanged
    .takeWhile(() => this.isAlive)
    .subscribe( evt => {
      if(!!evt){
        this.points = evt;

        if(!this.items){
          this.survey = this.fb.group({
            sections: this.fb.array([
              this.initSection(0),
            ]),
          });
          this.items = true;
        } else {
          this.addSection(this.points.length - 1);
        }
      }
    });
  }


  initSection(idx: number) {
    return this.fb.group({
      lat: [this.points[idx].lat],
      lon: [this.points[idx].lon],
    })
  }

  addSection(idx: number) {
    const control = <FormArray>this.survey.get('sections');
    control.push(this.initSection(idx));
  }

  getSections(form) {
    //console.log(form.get('sections').controls);
    return form.controls.sections.controls;
  }

  updateData(index: number){
    const values = this.survey.value.sections[index] as MapDetailModel;
    this.mapService.setChangePoint(values);
  }

  ngOnDestroy(): void {
    this.isAlive = false;
  }
}

html 文件:

<div class="main-wrapper">
    <div class="map-info-bar">
        <div class="blocco-info">
            {{lang.phrase('Coord')}}: {{lang.phrase('Lat')}} {{currentLatitude}} {{lang.phrase('Lon')}} {{currentLongitude}}
        </div>
        <div class="blocco-info">
            <dx-select-box [items]="zoomLevels" [value]="scale" (onValueChanged)="onScaleChange($event.value)">
            </dx-select-box>
        </div>
    </div>

    <div class="element-list">
        <form [formGroup]="survey" novalidate (ngSubmit)="onSubmit(survey)" *ngIf="items">
            <div formArrayName="sections">
                <div class="single-item" *ngFor="let section of getSections(survey); let i = index">
                    <div  [formGroupName]="i">
                        <input type="text" formControlName="lat" class="frm-txt">
                        <input type="text" formControlName="lon" class="frm-txt">
                        <a (click)="updateData(i)">Update data</a>
                    </div>
                </div>
            </div>
        </form>
    </div>
</div>

类:

export class MapDetailModel{
    lat: number;
    lon: number;
    alt: number;
    long?: number;
}

【问题讨论】:

  • 我认为您需要查看 formarray 而不是 formgroup。

标签: angular typescript


【解决方案1】:

问题可能与所有formControlNamengFor 中具有相同值有关。

先试试:

<span>Lat: </span> <input formControlName="lat{{i}}" type="text" value="{{p.lat}}">
<span>Lon: </span> <input formControlName="lon{{i}}" type="text" value="{{p.lon}}">

然后,在formGroup 中创建lonlat

this.points.forEach((point,index) => {
   this.formGroup.addControl("lat" + index, new FormControl());
   this.formGroup.addControl("lon" + index, new FormControl());
 });

您将能够访问每个控件。

【讨论】:

    【解决方案2】:

    我讨厌成为“那个”人,但我觉得这个代码示例是最好的,它不仅解释了嵌套表单的工作原理,还解释了如何引用表单中的单个项目。

    https://stackblitz.com/edit/deep-nested-reactive-form?file=app%2Fapp.component.html

    【讨论】:

    • 嗯,这是帮助我解决问题的唯一方法。谢谢老兄。
    • 为任何在同一个概念上苦苦挣扎的人保持链接。这也是帮助我更好地理解反应形式的原因。至少在我看来,它胜过大多数解释和例子。谢谢你,祝你编码愉快。
    • 我不得不简化一下,我已经删除了 90% 的代码以便正确理解,但它成功了。我在编辑中提到了您和您的答案,因此此链接将有效。
    【解决方案3】:

    试试这个代码可能对你有帮助。 只需查看代码然后进行更改,不要复制和粘贴只是阅读

    在您的 ts 代码上。

    form: FormGroup;
    
    ngOnInit() {
       this.initForm():
    }
    
    initForm() {
    
         this.form = new FormGroup({
            num_weeks: new FormControl(1, []),
            metric: new FormControl('sales', []),
            statistic: new FormControl('min', []),
            filters: filters
          });
    }
    

    在您的 HTML 组件上

    <form *ngIf="form" [formGroup]="form" novalidate>
               <mat-form-field appearance="fill" floatLabel="never" style="width: 360px; font-size: 14px;">
              <mat-label>Metric</mat-label>
              <mat-select #timeRange formControlName="metric" placeholder="Time range" placeholder="Type">
                <mat-option *ngFor="let type of types" [value]="type.value">
                  {{ type.name }}
                </mat-option>
              </mat-select>
            </mat-form-field>
    
            <mat-form-field appearance="fill" floatLabel="never" style="width: 360px; font-size: 14px;">
              <mat-label>Statistic</mat-label>
              <mat-select #timeRange formControlName="statistic" placeholder="" placeholder="Statistic">
                <mat-option *ngFor="let statistic of statistics" [value]="statistic.value">
                  {{ statistic.name }}
                </mat-option>
              </mat-select>
            </mat-form-field>
    </form>
    

    【讨论】:

      猜你喜欢
      • 2019-01-04
      • 1970-01-01
      • 2019-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-15
      • 1970-01-01
      相关资源
      最近更新 更多