首页 > 解决方案 > 如何将检查值放入 Angular 模板驱动表单 (ngModel) 的数组中

问题描述

我正在尝试使用模板驱动的表单,将 html 中的模型绑定到让说Person的新实例。我未能成功地为我的模型上的单个数组属性的复选框创建正确的绑定。

这个想法是数据将来自 api 或其他来源,通过动态呈现复选框*ngFor并将选择的内容绑定到Person模型属性,该属性将是一个数字数组。例如:

class Person {
  firstName: string;
  someCheckboxPropList: number[];
}

数据可以是任何东西

const dynamicData = [
  { name: 'name1', value: 1 },
  { name: 'name2', value: 2 }
];

我的预期输出将类似于 [ 1, 2 ]if 两个值都在哪里被检查,如果只有第二个被检查[ 2 ]

下面是 PersonComponent.ts 文件的示例

@Component({ ... })
export class PersonComponent {

    submitted = false;

    model = new Person();

    constructor() { }

    onSubmit(form) {
        this.submitted = true;
        console.log(form);
    }

}

我在哪里使用组件 html 文件。

<form (ngSubmit)="onSubmit(form)" #form="ngForm">

    <input type="text" [(ngModel)] name="person.firstName">

    <div *ngFor="let dataItem of dynamicData" >
        <input 
            type="checkbox"
            ngModel
            name="dynamicData"
            [value]="dataItem.value">
        <label>{{dataItem.name}}</label>
    </div>

</form>

这不起作用(无论如何都是示例代码)。

标签: angularangular-ngmodelangular-forms

解决方案


这个想法是有两件事:Person和PersonForm,所以,例如

person={firstName:"Jessy",props:[1,2]
//but 
personForm={firstName:"Jessy",props:[true,true]

所以,做两个函数

  createForm(person) {
    return {
      firstName: person.firstName,
      props: this.dynamicData.map(x => person.props.indexOf(x.value) >= 0)
    }
  }
  retrieveData(personForm) {
    let props: number[] = [];
    personForm.props.forEach((v, index) => {
      if (v)
        props.push(this.dynamicData[index].value)
    }
    )
    return {
      firstName: personForm.firstName,
      props: props
    }
  }

好吧,我们已经拥有了我们需要的一切。当我们收到一个人时,创建一个 personForm,它是我们在表单中更改的数据。在提交中只需调用retrieveData 来获取person 的值。

当我们让一个人创建一个personForm时,例如

this.service.getPerson().subscribe(person=>
    {
       this.personForm=createForm(person)
    }
)

我们的表格

<form *ngIf="personForm" (submit)="sendData(personForm)">
  <input name="firtName" [(ngModel)]="personForm.firstName">
  <div *ngFor="let item of dynamicData;let i=index">
  <input name="{{'prop'+i}}" 
         type="checkBox" [(ngModel)]="personForm.props[i]">{{item.name}}
  </div>
  <button>Submit</button>
</form>
{{personForm|json}}<br/>
{{retrieveData(personForm)|json}}

还有我们的 sendData 函数

sendData(personForm)
{
    console.log(this.retrieveData(personForm))
}

我做了一个简单的stackblitz

更新

注意:我们可以使用 spred 运算符来创建属性,所以

  createForm(person) {
    return {
      ...person, //All the properties of person, but
      props: this.dynamicData.map(x => person.props.indexOf(x.value) >= 0)
    }
  }
  retrieveData(personForm) {
    let props: number[] = [];
    personForm.props.forEach((v, index) => {
      if (v)
        props.push(this.dynamicData[index].value)
    }
    )
    return {
      ..personForm, //all the properties of personForm, but
      props: props
    }
  }

注意2:在“现实世界”中,这些人来自服务。考虑服务获取/接收“personForm”并将要转换的功能放在服务中的想法

//in service
getPerson()
{
    return this.httpClient.get("...").map(res=>this.createForm(res))
}
savePerson(personForm)
{
    return this.httpClient.post("...",this.retrieveData(personForm))
}

推荐阅读