【问题标题】:Two way binding of json map in AngularAngular中json映射的两种方式绑定
【发布时间】:2019-09-06 12:50:40
【问题描述】:

我是 Angular 新手,目前使用 Angular v.8。 我的组件中有一个 json 映射。我想使用此映射在 html 中创建我的输入字段(作为字段标签的键和作为输入值的值)。我已经迭代了这个地图并根据 json 地图数据填充了字段,但是编辑值并没有更新实际的 json 地图。我需要将组件中的更新地图发送到后端 API。请帮忙,下面的代码sn-ps:

组件: .. mapRecord: any = {"Col1":"Val1", "Col2":"Val2", "Col3":""} ...

html:

<table>
    <tr *ngFor="let record of mapRecord | keyvalue">
        <td>
            <div [formGroup]="addGlimpseForm">
                <mat-form-field> <input matInput
                    placeholder="{{record.key}}" [(ngModel)]="record.value"
                    formControlName="{{record.key}}" name="record.value" id="record.value">
            </mat-form-field>
            </div>
        </td>
    </tr>
</table>
{{ mapRecord | json }}

编辑: 我已经在组件中动态填充了表单控件:

 glimpseFields: string[] = [];
..
    for (var key in this.mapRecord) {
      this.glimpseFields.push(key);
    }
    this.addGlimpseForm = new FormGroup({username: new FormControl('', [])});
    for (let glimpseField of this.glimpseFields) {
      this.addGlimpseForm.addControl(glimpseField, new FormControl('', Validators.required));
    }

【问题讨论】:

  • 我看到 [formGroup]="addGlimpseForm" 表示响应式表单,[(ngModel)] 表示模板驱动表单。不要混用。

标签: angular


【解决方案1】:

mapRecord 未更新的原因是您在*ngFor 中使用的管道(即mapRecord | keyvalue)。此管道返回一个新对象 ([ { "key": "Col1", "value": "Val1" }, ... ]),因此对 mapRecord 的对象引用丢失。您需要使用响应式表单来处理值提交或将值映射到组件中的数组,然后在提交之前将它们映射回来。

为了解决这个问题,我只需将 mapRecord 映射到 ngOnChanges 中所有字段的数组(或任何有意义的地方,以便如果字段列表发生更改,逻辑将再次运行)。

每当调用onSubmit 函数时使用模板表单,表单的值将自动将其转换回您可以用来提交数据的对象。

组件:

export class Example implements OnChanges {
  @Input() public mapRecord?: any;

  public formFields: { key: string, value: string }[] = this.toFormFields({
    "Col1": "Val1",
    "Col2": "Val2",
    "Col3": "",
  });

  ngOnChanges() {
    this.formFields = this.toFormFields(this.mapRecord);
  }

  private toFormFields(data: any) {
    return Object.keys(data).map(key => ({ key, value: data[key] }));
  }

  public onSubmit(form: NgForm) {
    this.mapRecord = form.value;
    // Do submit logic
  }
}

模板:

<form (ngSubmit)="onSubmit(form)" #form="ngForm">
  <table>
    <tr *ngFor="let record of formFields">
      <td>
        <div>
          <mat-form-field>
            <input matInput
              [placeholder]="record.key"
              [(ngModel)]="record.value"
              [name]="record.key"
              [id]="record.value" />
          </mat-form-field>
        </div>
      </td>
    </tr>
  </table>
  <button type="submit" name="submit">Submit</button>
</form>

Stackblitz

【讨论】:

  • 哪种方法最好?另外,您能否提供实现细节,因为我是 Angular 新手。
  • 我试图通过使用@Ronak 提到的键对象来避免管道,但仍然是同样的错误。能否请你帮忙? keys : any; this.keys = Object.keys(this.mapRecord); &lt;table&gt; &lt;tr *ngFor="let key of keys"&gt; &lt;td&gt; &lt;div [formGroup]="addGlimpseForm"&gt; &lt;mat-form-field&gt; &lt;input matInput placeholder="{{key}}" [(ngModel)]="mapRecord[key]" formControlName="{{key}}" name="mapRecord[key]" id="mapRecord[key]"&gt; &lt;/mat-form-field&gt; &lt;/div&gt; &lt;/td&gt; &lt;/tr&gt; &lt;/table&gt;
  • 查看我的更新答案。请注意,这只是一种方法,但根据您的应用,可能会有更好的方法。
【解决方案2】:

您好,您只需进行少量更改即可获得密钥,而且它很有价值。 您必须为键创建对象。

mapRecord : any;
keys : any;
constructor(){
     this.mapRecord  =  {"Col1":"Val1", "Col2":"Val2", "Col3":""};
     this.keys = Object.keys(this.mapRecord);
}

下面你需要更新表格。

        <table>
    <tr *ngFor="let key of keys">
                <td>
                    <div [formGroup]="addGlimpseForm">
                        <mat-form-field> <input matInput
                            placeholder="{{key}}" [(ngModel)]="mapRecord[key]"
                            formControlName="{{key}}" name="mapRecord[key]" id="mapRecord[key]">
                    </mat-form-field>
                    </div>
                </td>
            </tr>
</table>

下面的例子对你有帮助。

https://stackblitz.com/edit/angular-13xuze

请查看上述更改,如果您有任何疑问,请告诉我。谢谢。

【讨论】:

  • @ShihadSalam 你能告诉我你在哪里遇到问题吗?
  • 最初的问题仍然存在。编辑输入字段时,mapRecord 值不会更新。更新的文本输入值未反映在实际地图对象 mapRecord 中。 record.value 显示更新后的值,但不显示 mapRecord。正如 Teddy 提到的,我在使用管道时丢失了这里的地图参考。但不知道如何在这里进行。也试过你的方法,但仍然没有运气!
【解决方案3】:

组件:test.component.ts


import { Component, Input, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
  @Input() public mapRecord?: any;

  public FormColumns: { key: string, value: string }[] = this.FormColumn({
    "Col1": "Val1",
    "Col2": "Val2",
    "Col3": "",
  });

  ngOnInit() {
    this.FormColumns = this.FormColumn(this.mapRecord);
  }

  private FormColumn(data: any) {
    return Object.keys(data).map(key => ({ key, value: data[key] }));
  }

  public onSubmit(form: NgForm) {
    this.mapRecord = form.value;
    // Do submit logic
  }

}

模板:test.component.html


    <form (ngSubmit)="onSubmit(recordForm)" #recordForm="ngForm">
    <table>
        <tr *ngFor="let formdata of FormColumns">
            <td>
                <div>
                    <mat-form-field>
                        <input matInput
              [placeholder]="formdata.key"
              [(ngModel)]="formdata.value"
              [name]="formdata.key"
              [id]="formdata.value" />
          </mat-form-field>
        </div>
      </td>
    </tr>
  </table>

    <button type="submit" name="submit">Submit</button>
  </form>
  <br>
  FormColumns: <pre>{{ FormColumns | json }}</pre>
  mapColumn: <pre>{{ mapRecord | json }}</pre>

Stackblitz

【讨论】:

  • 已经在组件中填充了表单组,仍然是同样的问题。
  • @ShihadSalam 你能告诉我你在哪里遇到问题吗?
  • 从@Teddy Sterne 复制答案不公平!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-07
  • 2019-02-27
  • 2014-02-25
  • 1970-01-01
  • 2018-10-26
  • 2020-07-07
  • 1970-01-01
相关资源
最近更新 更多