Динамически добавлять несколько элементов управления формы - PullRequest
0 голосов
/ 25 июня 2019

У меня есть компонент, который создает элемент управления формы с опциями «добавить другое поле» и «удалить это поле» на основе объекта шаблона.

Например, для этого шаблона:

assignmentLinkTemplateObj = {
    name: 'Name',
    url: 'URL'
}

должен создать 2 текстовых поля с именами полей 'name' и 'url' и местозаполнителями 'Name' и 'URL'. Теперь компонент добавляет эти поля одним нажатием кнопки «Добавить другое назначение». И удаляет комбинацию этих 2 полей при нажатии «удалить это назначение».

Аналогично, если шаблон:

pastTopicalLinkTemplateObj = {
    name: 'Name',
    type: ['ER', 'MS', 'GT', 'QP'],
    url: 'URL'
}

Тип является массивом, поэтому компонент будет отображать раскрывающийся список со значениями этого массива.

Вот что я сделал:

Markup:

<form nz-form [formGroup]="validateForm">
  <nz-form-item *ngFor="let control of controlArray; let i = index">
    <nz-form-label [nzXs]="24" [nzSm]="6" *ngIf="i == 0" [nzFor]="control[field]">
        <!-- RENDER DROPDOWNS OR TEXT FIELDS -->
        <ng-container *ngFor="let field of objectKeys(fieldsTemplate)">
            <nz-select *ngFor="let option of fieldsTemplate[field]" *ngIf="isObj(fieldsTemplate[field])">
                <nz-option [nzLabel]="option" [nzValue]="option"></nz-option>
            </nz-select>
            <input 
                *ngIf="!isObj(fieldsTemplate[field])"
                nz-input
                style="margin-right:8px;"
                [placeholder]="fieldsTemplate[field]"
                [attr.id]="control.id"
                [formControlName]="control['id']+control[field]"
            />
        </ng-container>

        <!-- REMOVE FIELD -->
        <i nz-icon type="minus-circle-o" class="dynamic-delete-button" (click)="removeField(control['id'], $event)"></i>
      </div>
    </nz-form-control>
  </nz-form-item>
  <nz-form-item>
    <nz-form-control [nzXs]="{ span: 24, offset: 0 }" [nzSm]="{ span: 20, offset: 6 }">
        <!-- ADD ANOTHER FIELD -->
        <button nz-button nzType="dashed" style="width:inherit;" (click)="addField($event)">
            <i nz-icon type="plus"></i> Add
        </button>
    </nz-form-control>
  </nz-form-item>
</form>

Component.ts:

validateForm: FormGroup;

@Input('name') name;
@Input('fieldsTemplate') fieldsTemplate;
@Input('error_text') error_text;

@Input('controlArray') controlArray: any = [];

@Output('valueAdd') valueAdd = new EventEmitter();
@Output('valueRemove') valueRemove = new EventEmitter();

objectKeys = Object.keys;

keys;

isObj(obj) {
  return typeof obj == 'object';
}

addField(e ? : MouseEvent): void {
  if (e) {
    e.preventDefault();
  }
  const id = this.controlArray.length > 0 ? this.controlArray[this.controlArray.length - 1].id + 1 : 0;

  this.keys = Object.keys(this.fieldsTemplate);

  const control = {
    id
  };

  this.keys.forEach(key => {
    control[key] = key;
  });

  const index = this.controlArray.push(control);

  this.keys.forEach(key => {
    this.validateForm.addControl(
      `${id}${this.controlArray[index - 1][key]}`,
      new FormControl(null, Validators.required)
    );
  })

  this.valueAdd.emit(this.controlArray);
}

removeField(id, e: MouseEvent): void {
  e.preventDefault();
  if (this.controlArray.length > 1) {
    const index = this.getControlById(id);
    this.controlArray.splice(index, 1);
    this.keys.forEach(key => {
      this.validateForm.removeControl(`${id}${this.controlArray[index - 1][key]}`);
    });
    this.valueRemove.emit(this.controlArray[index]);
  }
}

getControlById(id) {
  let index;
  this.controlArray.filter((control, i) => {
    if (control.id === id) {
      index = i;
    }
  });
  return index;
}

getFormControl(id: string): AbstractControl {
  return this.validateForm.controls[this.getControlById(id)];
}

constructor(private fb: FormBuilder) {}

ngOnInit(): void {
  this.validateForm = new FormGroup({

  });
}

Проблема: this.validateForm.value теперь дает мне объект, похожий на этот:

{0name: "asd", 0url: "asd", 1name: "asd1", 1url: "asd2"}

Есть ли способ, которым я могу сделать это по-другому и сопоставить мои элементы управления формой с массивом объектов таким образом, чтобы каждая комбинация полей была объектом, а вся форма была массивом этих объектов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...