Angular RxFormBuilder и массив строк - PullRequest
0 голосов
/ 06 апреля 2020

Я пытаюсь отправить в бэкэнд форму, которая ожидает следующую структуру JSON:

{
    name: "stringName",
    allowedFields: []
}

У меня есть объект модели для этого

export class MyClass {
  @required()
  name: string;

  @propArray(String)
  allowedFields: Array<String>;
}

В документации они всегда говорят о пользовательских объектах, но не о базовых c типах, таких как строковые массивы: https://www.npmjs.com/package/@rxweb / реактивные-формы-валидаторы / v / 1.2.2? activeTab = readme # дополнительная информация-о-валидаторы-и -validation-decorators

В html я пытаюсь использовать Bootstrap Переключатели для отображения набора возможных значений, которые должны быть отправлены в бэкэнд следующим образом:

<div [formGroup]="field" *ngFor="let field of myFormGroup.controls.allowedFields.controls">
    <div class="custom-control custom-switch">
      <input type="checkbox" class="custom-control-input"
             [value]="field.memberName">
      <label class="custom-control-label">{{field.memberName}}</label>
    </div>
</div>

Кто-нибудь знает, как добиться отправки массива строк на сервер? Cheers Maik

1 Ответ

1 голос
/ 06 апреля 2020

ПРИМЕЧАНИЕ: эта первая часть НЕ для вашей проблемы. В общем, когда вам нужно, форма должна быть похожа на

form=new FormGroup({
  name:new FormControl(),
  allowedFields:new FormArray([]);
})

Так что сделайте три функции и получатель и объявите переменную форму:

form:FormGroup;

get allowedFields()
{
    return this.form.get('allowedFields') as FormArray;
}

getForm(data:any)
{
   data=data||{data:null,allowedFields:[]}
   return new FormGroup({
      name:new FormControl(data.name),
      allowedFields:new FormArray(data.allowedFields.map(x=>new FormControl(x)))
    }) 
}
addAllowedField(data:string)
{
    this.allowedFields.push(new FormControl(data));
}
removeAlloedField(index)
{
    this.allowedFields.removeAt(index)
}

Ваш. html

<form [formGroup]="form" (submit)="submit(form)">
  <input formControlName="name">
  <div formArrayName="allowedFields">
    <button type="button" (click)="addAllowedField(null)">add</button>
  <div *ngFor="let control of allowedFields.controls;let i=index" >
    <input [formControlName]="i">
    <button type="button" (click)="removeAllowedField(i)">remove</button>
  </div>
  </div>
  <button type="submit">submit</button>
</form>

Видите, что вы пишете <div formArrayName="allowedFields"> и перебираете allowedFields.controls - это "геттер", определенный в .ts. Для управления «входом» вы можете использовать [formControlName]="i" (или [formControl]="control" -control - это переменная * ngFor

ЭТА ЧАСТЬ - это ваш ВОПРОС

Но вы хотите серию флажок и отправить и массив с выбранными значениями, так что ваша форма это только два поля массив «позволенных полей», сделайте его массивом объектов, например,

fieldList=[
   {id:1,name:"field one"},
   {id:2,name:"field two"},
   {id:3,name:"field three"},
]

Мы собираемся использовать входные данные, которые не принадлежат к formGroup, да [(ngModel)] в ReactiveForms

<form [formGroup]="form" (submit)="submit(form)">
  <input formControlName="name">
  <div *ngFor="let item of fieldList;let i=index" >
    <input type="checkbox"
        [ngModel]="item.check" 
        (ngModelChange)="item.check=$event;setAllowedFields()"
         [ngModelOptions]="{standalone:true}"
    >{{item.name}}
  </div>
  <button type="submit">submit</button>
</form>

И функция

setAllowedFields()
{
   this.form.get('allowedFields').setValue(this.fieldList
           .filter(x=>x.checked)
           .map(x=>x.id))
}

См. stackblitz

Обновление для предварительного заполнения чеков, как всегда, у нас есть функция вернуть формуГруппа

getGroup(data)
{
   data=data || {name:'',allowedFields:[]}

   //prepopulate the data
   this.fieldList.forEach(x=>{
       x.check=data.indexOf(x.id>=0)
   })
   /* //or 
   allowedField.forEach(x=>{
     const field=this.fieldList.find(f=>f.id==x)
     if (field)
         field.check=true;
   })
   */
   return new FormGroup({
          name:new FormControl(data.name),
          allowedFields:new FormControl(data.allowedFields);
    })

}  

Вы используете как

   this.form=this.getGroup(null) //<--a empty form
   this.form=this.getGroup(data) //<-- a form with data
...