如何仅在 Angular 反应式表单中触摸表单字段后才显示验证错误

问题描述 投票:0回答:1

我有一个 component.ts 文件:

import { Component } from "@angular/core";
import {
  FormBuilder,
  FormControl,
  FormGroup,
  Validators,
} from "@angular/forms";
import { FaIconLibrary } from "@fortawesome/angular-fontawesome";
import { fas } from "@fortawesome/free-solid-svg-icons";

@Component({
  selector: "app-course-form",
  templateUrl: "./course-form.component.html",
  styleUrls: ["./course-form.component.scss"],
})
export class CourseFormComponent {
  constructor(
    public fb: FormBuilder,
    public library: FaIconLibrary
  ) {
    library.addIconPacks(fas);
  }

  profileForm = this.fb.group({
    title: ["", [Validators.required, Validators.minLength(2)]],
    description: ["", [Validators.required, Validators.minLength(10)]],
    author: ["", [Validators.required, Validators.pattern(/^[a-zA-Z0-9 ]+$/)]],
    duration: [0, [Validators.required, Validators.min(1)]],
  });

  courseForm!: FormGroup;
  title = new FormControl("");
  description = new FormControl("");
  author = new FormControl("");
  duration = new FormControl(0);

  authors: any[] = [];
  durationText: string = "";
  submitted = false;

  removeAuthor(author: string) {
    this.authors = this.authors.filter((a) => a !== author);
  }

  getDurationFormatted(minutes: number): string {
    const hours = Math.floor(minutes / 60);
    const mins = minutes % 60;
    return `${hours.toString().padStart(2, "0")}:${mins
      .toString()
      .padStart(2, "0")}`;
  }
}

和 html 组件:

<h2>Create / Edit Course</h2>
<form [formGroup]="profileForm">
  <div class="app-plate">
    <div class="course">
      <h3>Main Info</h3>
      <div class="form__control">
        <label for="title">Title</label>
        <input type="text" id="title" placeholder="Input text" />
        <span
          *ngIf="profileForm.invalid"
          id="titleErrorMessage"
          class="text-danger"
          >Title is required.</span
        >
      </div>
      <div class="form__control">
        <label for="description">Description</label>
        <textarea
          id="description"
          placeholder="Input text"
          rows="4"
          cols="5"
        ></textarea>
        <span
          *ngIf="profileForm.invalid && profileForm.value.description"
          id="descriptionErrorMessage"
          class="text-danger"
          >Description is required.</span
        >
      </div>
      <div class="separator"></div>
      <h3>Authors</h3>
      <div class="form__control">
        <div class="course__flex">
          <input type="text" id="author" placeholder="Input Author Name" />
          <app-button
            id="createAuthor"
            button_text="Create author"
          ></app-button>
        </div>
        <span *ngIf="" id="authorErrorMessage"
          >New author should contain only latin letters and numbers.</span
        >
        <div class="course__authors">
          <ul class="authors-list">
            <li
              *ngFor="let author of authors; track: author"
              class="authors-list-item"
            >
              Id: {{ author.id }}. Name: {{ author.name }}
              <app-button button_text="Remove" (click)="removeAuthor(author)">
              </app-button>
            </li>
          </ul>
        </div>
      </div>
      <div class="separator"></div>
      <h3>Duration</h3>
      <div class="form__control">
        <div class="course__flex">
          <input
            type="number"
            id="duration"
            placeholder="Input duration"
            formControlName="duration"
          />
          <div class="course__duration">
            <strong> </strong>
            hours
          </div>
        </div>
        <span *ngIf="" id="durationErrorMessage" class="text-danger"
          >Duration is required and must be greater than 0.</span
        >
      </div>
      <div class="form__action"></div>
    </div>
  </div>
</form>
<div class="buttons-container">
  <app-button button_text="Cancel"></app-button>
  <app-button button_text="Create course"></app-button>
</div>

我想展示:

 <span
          *ngIf="profileForm.invalid "
          id="titleErrorMessage"
          class="text-danger"
          >Title is required.</span
        >

仅当输入字段被触摸且仍然无效时。现在错误显示在加载的新表单上。怎么办?

以下: 在 Angular 中使用反应式形式受到感动并有效

我尝试使用表单控件,例如:

 <div class="form__control">
        <label for="title">Title</label>
        <input
          type="text"
          id="title"
          placeholder="Input text"
          [formControl]="title"
        />
        <span
          *ngIf="profileForm.invalid && profileForm.controls['title'].touched"
          id="titleErrorMessage"
          class="text-danger"
          >Title is required.</span
        >
      </div>

但是没有成功。

angular
1个回答
0
投票

title
控件的验证不正确,因为您应该验证特定控件,而不是整个表单,如下所示:

<span
   *ngIf="profileForm.controls.get('title').invalid && profileForm.controls.get('title').touched"
    id="titleErrorMessage"
    class="text-danger"
 >Title is required.</span>

如果您使用 Angular 版本 14 或更高版本,您可以为表单提供强类型输入,这是一件好事。

<form [formGroup]="form">
   <label for="name">Enter name</label>
   <input type="text" id="name" formControlName="name" />
   
    @if(form.controls.name.invalid && form.controls.name.touched) {
    <span style="color: red">Name is required or invalid</span>
    }
</form>

组件.ts

interface MyForm {
  name: FormControl<string | null>;
}


@Component({...})
export class MyComponent implements OnInit {
  private _fb = inject(FormBuilder);
  protected form!: FormGroup<MyForm>; //form of type MyForm

  ngOnInit(): void {
    this.form = this._fb.group<MyForm>({
      name: new FormControl(null, Validators.required),
    });
  }
}

观看演示

© www.soinside.com 2019 - 2024. All rights reserved.