Динамическая форма с использованием * ngFor и отправка значений из нее - PullRequest
0 голосов
/ 10 декабря 2018

У меня есть stackblitz в качестве руководства.

Я хочу отобразить список карточек материалов, которые я нажимаю на кнопку «Изменить», для которойЯ могу редактировать текстовые поля, и когда я нажимаю на значок «сохранить», он, конечно, сохраняет, вызывая функцию и т. Д.

Однако я пытаюсь понять, как все это работает в Angular иМатериальная природа моего приложения.

html

<form id="myForm" [formGroup]="thisIsMyForm">
  <mat-card [formGroup]="x" *ngFor="let x of data; let i = index">
    <mat-form-field>
      <label for="{{x.name}}">Name</label>
      <input formControlName="name" id="{{x.name}}" matInput value="{{x.name}}">
    </mat-form-field>
    <mat-form-field>
      <label for="{{x.type}}">Type</label>
      <input formControlName="type" id="{{x.type}}" matInput value="{{x.type}}"/>
    </mat-form-field>
  </mat-card>
</form>

ts

import { Component, ViewChild } from '@angular/core';
import {MatSnackBar} from '@angular/material';
import {FormArray, FormBuilder, FormGroup, Validators} from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  thisIsMyForm: FormGroup

  data = [
    {name:"one", type:"one"},
    {name:"two", type:"two"},
    {name:"three", type:"three"},
  ];

  constructor(private formBuilder: FormBuilder) {}

  onSubmit() {
    // Here I would like to be able to access the values of the 'forms'
  }

}

Ответы [ 2 ]

0 голосов
/ 10 декабря 2018

Вы точно погрузитесь в глубокий конец, пытаясь создать динамическую реактивную форму в рамках *ngFor - это непростая задача.Я проведу вас через все, что смогу.

Вам нужно будет создать массив для элементов управления, в вашем конструкторе создайте настройку формы formArrayName как пустой массив, используя this.formBuild.array([]) ... вызовите этовсе, что вы хотите, я просто использовал formArrayName в демонстрационных целях.

После создания экземпляра формы с помощью пустого массива вызовите this.buildForm()

constructor(private formBuilder: FormBuilder) {
    this.thisIsMyForm = new FormGroup({
      formArrayName: this.formBuilder.array([])
    })

    this.buildForm();
  }

В вашем buildForm() итерируйте ваш data[] и нажимайте элементы управления для каждого индекса, назначая значение по умолчаниюи состояние по умолчанию отключено.

 buildForm() {
    const controlArray = this.thisIsMyForm.get('formArrayName') as FormArray;

    Object.keys(this.data).forEach((i) => {
      controlArray.push(
        this.formBuilder.group({
          name: new FormControl({ value: this.data[i].name, disabled: true }),
          type: new FormControl({ value: this.data[i].type, disabled: true })
        })
      )
    })

    console.log(controlArray)
  }

Обратите внимание: console.log (controlArray.controls) приводит к следующему выводу ... каждый индекс представляет собой группу FormGroup с двумя элементами управления name и type

0: FormGroup
1: FormGroup
2: FormGroup

В вашем html вам необходимо установить иерархию контейнеров, которая имитирует thisIsMyForm, который вы только что создали.

  • родитель: thisIsMyForm
  • ребенок: formArrayName
  • внук: i as formGroupName

внукважно, потому что он соответствует журналу консоли controlArray.controls на предыдущем шаге

<form id="myForm" [formGroup]="thisIsMyForm">
    <div [formArrayName]="'formArrayName'">
        <mat-card *ngFor="let x of data; let i = index">
            <div [formGroupName]="i">

Создание кнопок редактирования и сохранения на основе отключенного состояния элемента управления

   <button *ngIf="fomrControlState(i)" (click)="toggleEdit(i)">Enable Edit</button>
    <button *ngIf="!fomrControlState(i)" (click)="toggleEdit(i)">Save</button>

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

toggleEdit(i) {
    const controlArray = this.thisIsMyForm.get('formArrayName') as FormArray;
    if(controlArray.controls[i].status === 'DISABLED'){
      controlArray.controls[i].enable()
    }else{
      controlArray.controls[i].disable()
    }
  }

  fomrControlState(i){
     const controlArray = this.thisIsMyForm.get('formArrayName') as FormArray;
     return controlArray.controls[i].disabled
  }

Отправить кнопку, в которой console.log будет значением формы при нажатии ... также отключить кнопку, когда любой извходные данные формы управления находятся во включенном состоянии.

<button [disabled]="thisIsMyForm.get('formArrayName').enabled" (click)="onSubmit()">Submit Form</button>

onSubmit() {
    // Here I would like to be able to access the values of the 'forms'
    console.log(this.thisIsMyForm.value)
  }

Stackblitz

https://stackblitz.com/edit/dynamic-form-ngfor-otbuzn?embed=1&file=src/app/app.component.ts

0 голосов
/ 10 декабря 2018

Делая это с QueryList:

вашим html (это пример):

<ng-container *ngFor="let x of data; let i = index">
  <div class="ctr">
    <span #names class="item">{{x.name}}</span>
    <span #types class="item">{{x.type}}</span>
    <span class="button" (click)="showData(i)">Show data</span>
  </div>

</ng-container>

<h2>Selected values: </h2>
Selected name: {{selectedName}} <br>
Selected type: {{selectedType}}

немного CSS только для стиля

.ctr{
  display: flex;
  flex-direction: row;
  margin-bottom: 20px;
}

.item{
  margin-right:40px;
}

.button{
  border: 1px solid black;
  padding: 2px 5px 2px 5px;
  cursor: pointer;
}

компонент:

import { Component, QueryList, ViewChildren } from '@angular/core';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent  {
  @ViewChildren('names') names:QueryList<any>;
  @ViewChildren('types') types:QueryList<any>;

  selectedName: string;
  selectedType: string;

  data = [
    {name:"one", type:1},
    {name:"two", type:2},
    {name:"three", type:3},
  ];

  showData(index){
    let namesArray = this.names.toArray();
    let typesArray = this.types.toArray();

    this.selectedName = namesArray[index].nativeElement.innerHTML;
    this.selectedType = typesArray[index].nativeElement.innerHTML;
  }
}

Рабочий стек стека: https://stackblitz.com/edit/angular-j2n398?file=src%2Fapp%2Fapp.component.ts

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