简体   繁体   English

Angular 反应式表单不显示内置验证器错误消息

[英]Angular Reactive form does not show built-in validator error message

I was working with angular reactive form validation and I got an unexpected problem.我正在使用 angular 反应式表单验证,但遇到了一个意想不到的问题。 I created a built-in validator to filter out restricted words from a textarea.我创建了一个内置验证器来过滤掉文本区域中的受限单词。 The code was supposed to identify the restricted words, and if they appear on the textarea, it would mark the textarea as invalid and display an error message on top of the textarea ie "Restricted words found: foo, bar" The textarea has other validations in place such as required and maxLength(400) , which work fine and display error messages.该代码应该识别受限制的单词,如果它们出现在 textarea 上,它会将 textarea 标记为无效并在 textarea 顶部显示一条错误消息,即“Restricted words found: foo, bar” textarea 有其他验证到位,例如requiredmaxLength(400) ,它们可以正常工作并显示错误消息。 The problem I'm having only occurs with the custom validator.我遇到的问题只发生在自定义验证器上。 Although the textarea correctly identifies the restricted words and marks the field as invalid, the error message does not display.尽管 textarea 正确识别了受限制的单词并将该字段标记为无效,但不会显示错误消息。 What could be the issue?可能是什么问题? I got no errors from npm or the console. npm 或控制台没有错误。

Here is my component class: create-session.component.ts这是我的组件 class: create-session.component.ts

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ISession, restrictedWords } from '../shared/index';

@Component({
    templateUrl: 'create-session.component.html',
    styles: [`
      em { float: right; color: #E05C65; padding-left: 10px; }
      .error input, .error select, .error textarea { background-color: #E3C3C5; }
      .error ::-webkit-input-placeholder { color: #999; }
      .error ::-moz-placeholder { color: #999; }
      .error :ms-input-placeholder { color: #999; }
    `]
})

export class CreateSessionComponent implements OnInit {
    newSessionForm:FormGroup
    name:FormControl
    presenter:FormControl
    duration:FormControl
    level:FormControl
    abstract:FormControl

    constructor() {}

    ngOnInit() {
        this.name = new FormControl('', Validators.required)
        this.presenter = new FormControl('', Validators.required)
        this.duration = new FormControl('', Validators.required)
        this.level = new FormControl('', Validators.required)
        this.abstract = new FormControl('', [Validators.required, Validators.maxLength(400), restrictedWords(['foo', 'bar'])])

        this.newSessionForm = new FormGroup({
            name: this.name,
            presenter: this.presenter,
            duration: this.duration,
            level: this.level,
            abstract: this.abstract
        })
    }

    saveSession(formValues) {
        let session:ISession = {
            id: undefined,
            name: formValues.name,
            duration: +formValues.duration,
            level: formValues.level,
            presenter: formValues.presenter,
            abstract: formValues.abstract,
            voters: []
        }

        console.log(session)
    }
}

Here is my component html: create-session.component.html这是我的组件 html: create-session.component.html

<div class="col-md-12">
  <h3>Create Session</h3>
</div>
<div class="col-md-6">
  <form [formGroup]="newSessionForm" (ngSubmit)="saveSession(newSessionForm.value)" autocomplete="off">
    <div class="form-group" [ngClass]="{ 'error': name.invalid && name.dirty}" >
      <label for="sessionName">Session Name:</label>
      <em *ngIf="name.invalid && name.dirty">Required</em>
      <input formControlName="name" id="sessionName" type="text" class="form-control" placeholder="session name..." />
    </div>
    <div class="form-group" [ngClass]="{ 'error': presenter.invalid && presenter.dirty}" >
      <label for="eventDate">Presenter:</label>
      <em *ngIf="presenter.invalid && presenter.dirty">Required</em>      
      <input formControlName="presenter" id="presenter" type="text" class="form-control" placeholder="presenter..." />
    </div>
    <div class="form-group" [ngClass]="{ 'error': duration.invalid && duration.dirty}" >
      <label for="duration">Duration:</label>
      <em *ngIf="duration.invalid && duration.dirty">Required</em>      
      <select formControlName="duration" class="form-control">
        <option value="">select duration...</option>
        <option value="1">Half Hour</option>
        <option value="2">1 Hour</option>
        <option value="3">Half Day</option>
        <option value="4">Full Day</option>
      </select>
    </div>
    <div class="form-group" [ngClass]="{ 'error': level.invalid && level.dirty}" >
      <label for="level">Level:</label>
      <em *ngIf="level.invalid && level.dirty">Required</em>      
      <select formControlName="level" class="form-control">
        <option value="">select level...</option>
        <option value="Beginner">Beginner</option>
        <option value="Intermediate">Intermediate</option>
        <option value="Advanced">Advanced</option>
      </select>
    </div>
    <div class="form-group" [ngClass]="{ 'error': abstract.invalid && abstract.dirty}" >
      <label for="abstract">Abstract:</label>
      <em *ngIf="abstract.invalid && abstract.dirty && abstract?.errors.required">Required</em> 
      <em *ngIf="name.invalid && name.dirty && abstract?.errors.maxlength">Cannot exceed 400 characters</em>     
      <em *ngIf="name.invalid && name.dirty && abstract?.errors.restrictedWords">
        Restricted words found: {{abstract.errors.restrictedWords}}
      </em>
      <textarea formControlName="abstract"  id="abstract" rows=3 class="form-control" placeholder="abstract..."></textarea>
    </div>
    <button type="submit" class="btn btn-primary" [disabled]="newSessionForm.invalid">Save</button>
    <button type="button" class="btn btn-default">Cancel</button>
  </form>
</div>

Here is my custom validator: restricted-words.validator.ts这是我的自定义验证器: restricted-words.validator.ts

import { FormControl } from '@angular/forms';

export function restrictedWords(words) {
    return (control: FormControl): {[key: string]: any} => {
        if(!words) return null

        var invalidWords = words
            .map(w => control.value.includes(w) ? w : null) 
                .filter(w => w != null)

        return invalidWords && invalidWords.length > 0 
        ? {'restrictedWords' : invalidWords.join(', ')} 
        : null
    }
}

Here's a github repo if it helps: https://github.com/AshrafLobo/Angular-Demo如果有帮助,这里是github 回购https://github.com/AshrafLobo/Angular-Demo

It's just a small copy-paste error, you have to replace name with abstract这只是一个小的复制粘贴错误,您必须将name替换为abstract

     <div class="form-group" [ngClass]="{ 'error': abstract.invalid && abstract.dirty}" >
      <label for="abstract">Abstract:</label>
      <em *ngIf="abstract.invalid && abstract.dirty && abstract?.errors.required">Required</em> 
      <em *ngIf="abstract.invalid && abstract.dirty && abstract?.errors.maxlength">Cannot exceed 400 characters</em>     
      <em *ngIf="abstract.invalid && abstract.dirty && abstract?.errors.restrictedWords">
        Restricted words found: {{abstract.errors.restrictedWords}}
      </em>
      <textarea formControlName="abstract"  id="abstract" rows=3 class="form-control" placeholder="abstract..."></textarea>
    </div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM