NgFor内的ReactiveForm

时间:2018-09-18 13:08:27

标签: angular typescript

我有一个ngFor,它在reactForm里面。这是代码:

<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中得到的都是null和null值。

问题

我的问题是,当我单击按钮时,如何“知道”我要引用的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;
}

3 个答案:

答案 0 :(得分:1)

我讨厌成为那个人,但是我觉得这个代码示例是最好的示例,它不仅可以解释嵌套表单的工作方式,而且还可以解释如何引用表单中的单个项目。

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

答案 1 :(得分:0)

尝试此代码可能会对您有所帮助。 只需查看代码,然后进行更改,就不要复制并粘贴已读

在您的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>

答案 2 :(得分:0)

该问题可能与以下事实有关:所有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}}">

然后,在lon中分别创建latformGroup

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

您将能够访问每个控件。