Formularz bierny o dynamicznej walidacji Patten jest zawsze nieprawidłowy przy pierwszym obciążeniu. Nawet po edycji nadal nieważny.

Dzieje się tak tylko wtedy, gdy dodam dynamiczny wzór dopasowywania weryfikacji.

Oto mój przypadek użycia:

  • Na interfejsie użytkownika jest tabelę i przycisk edycji w ostatnim rzędzie
  • Początkowo nie widać żadnych formontroli
  • Użytkownik kliknie przycisk Edytuj, a następnie pojawia się sterowanie formą.

Odnoszą się o tym Stackblitz .

Poniżej znajduje się kod

<form [formGroup]="data_form">
    <table class="table table-border">
        <thead>

            <th>
                name
            </th>
            <th>
                age
            </th>
            <th><button class="btn btn-primary ">Save</button></th>
        </thead>
        <tbody>
            <ng-container *ngFor='let item of data;let j = index'>
                <tr>
                    <ng-container *ngFor="let td of keys;let i = index">
                        <ng-container>

                            <td  *ngIf="td !=='isEditable'">
                                {{item[td]}}
                                <input   [formControlName]="getControlName(j,i)" *ngIf="item.isEditable" type="text" name="" id="">
          </td>

                        </ng-container>
                    </ng-container>

                    <td>
                        <button (click)="item.isEditable = true"> Edit</button>
                    </td>
                </tr>
            </ng-container>
        </tbody>
    </table>

</form>

Kod TS:

import { Component } from "@angular/core";
import { FormControl, FormGroup, Validators } from "@angular/forms";

@Component({
  selector: "my-app",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  name = "Angular";
  data_form = new FormGroup({});
  public data;
  keys;

  ngOnInit() {
    this.data = [
      {
        name: "Sachin",
        age: 27,

        isEditable: false
      },
      {
        name: "Gopal",
        age: 27,

        isEditable: false
      },
      {
        name: "Pankaj",
        age: 24,

        isEditable: false
      }
    ];
    this.keys = Object.keys(this.data[0]);
    this.data.forEach((element, j) => {
      this.keys.forEach((k, i) => {
        this.data_form.addControl(
          "name_" + j + "_" + i,
          new FormControl(element[k], [Validators.required, Validators.pattern(/^[.\d]+$/)])
        );
      });
    });
  }

  log() {
    console.log(this.data);
  }

  getControlName(j, i) {
    return "name_" + j + "_" + i;
  }
}

Z góry dziękuję.

EDYTOWAĆ:

Różne wzory, które używałem:

  • Validators.pattern("^[a-zA-Z0-9 _/]+$")
  • Validators.pattern(/^[.\d]+$/)
  • Validators.pattern(/^(yes|no)$/i)
  • Validators.pattern(/^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/)
1
user1608841 17 październik 2020, 17:27

1 odpowiedź

Najlepsza odpowiedź

Problem polega na tym, że wzór jest używany do wszystkich elementów sterujących. Oddałem swój kod za pomocą FormArray i wydaje się, że twój wzór działa dobrze

Poniżej to moje podejście plik TS

  constructor(private fb: FormBuilder) {}
  patterns = [
    /^[.\d]+$/,
    /^(yes|no)$/i,
    /^[a-zA-Z0-9 _/]+$/,
    /^(0[1-9]|1[0-2])\/(0[1-9]|1\d|2\d|3[01])\/(19|20)\d{2}$/
  ];
  data = [
    {
      name: "Sachin",
      age: 27,
      isEditable: false
    },
    {
      name: "Gopal",
      age: 27,

      isEditable: false
    },
    {
      name: "Pankaj",
      age: 24,

      isEditable: false
    }
  ];
  keys = [...new Set(this.data.map(item => Object.keys(item)).flat())];
  keyPattern = this.keys.map(item => ({
    key: item,
    pattern: this.patterns.find(pattern =>
      this.data.every(i => pattern.test(i[item]))
    )
  }));
  data_form = this.fb.group({
    persons: this.fb.array(
      this.data.map(item =>
        this.fb.group(
          this.keyPattern.reduce(
            (prev, { key, pattern }) => ({
              ...prev,
              [key]: [
                item[key],
                [Validators.required, Validators.pattern(pattern)]
              ]
            }),
            {}
          )
        )
      )
    )
  });
  get persons(): FormArray {
    return this.data_form.get("persons") as FormArray;
  }

  toggleEdit(j) {
    const currentEditStatus = this.persons.controls[j].get("isEditable").value;
    this.persons.controls[j].get("isEditable").setValue(!currentEditStatus);
  }

HTML

<form [formGroup]="data_form">
    <table class="table table-border">
        <thead>
      <tr>
        <th> name </th>
            <th>age </th>
            <th><button class="btn btn-primary ">Save</button></th>
      </tr>
        </thead>
        <tbody formArrayName='persons'>
            <ng-container *ngFor='let item of persons.controls;let j = index'>
                <tr [formGroupName]='j'>
                    <ng-container *ngIf="!item.value.isEditable; else editable">
                        <td>{{ item.value.name }}</td>
                        <td>{{ item.value.age }}</td>
                    </ng-container>
                    <ng-template #editable>
                        <td><input formControlName='name'></td>
                        <td><input formControlName='age'></td>
                    </ng-template>
                    <td>
                        <button (click)="toggleEdit(j)">
              {{ !item.value.isEditable ? "Edit": "Cancel"}}
            </button>
                    </td>
                </tr>
            </ng-container>
        </tbody>
    </table>

</form>

Patrz poniżej widelca Demo

1
Owen Kelvin 17 październik 2020, 19:03