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

时间:2019-10-03 11:47:39

标签: angular

我正在使用角度反应形式验证,但遇到了意外问题。我创建了一个内置验证器,以从文本区域中过滤出受限词。该代码应该可以识别限制词,如果它们出现在文本区域中,则会将文本区域标记为无效,并在文本区域顶部显示错误消息,即“找到限制词:foo,bar” 文本区域还有其他验证,例如必需 maxLength(400),它们可以正常工作并显示错误消息。我遇到的问题仅与自定义验证程序有关。尽管文本区域可以正确识别受限词并将该字段标记为无效,但是不会显示错误消息。可能是什么问题?我没有从npm或控制台中得到任何错误。

这是我的组件类: 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)
    }
}

这是我的组件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>

这是我的自定义验证器: 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
    }
}

这是一个 github存储库(如果有帮助的话):https://github.com/AshrafLobo/Angular-Demo

1 个答案:

答案 0 :(得分:1)

这只是一个很小的复制粘贴错误,您必须将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>