Angular2 формирует сообщения об ошибках проверки

Я новичок в Angular и JavaScript в целом, я пытаюсь добавлять сообщения, когда пользовательский ввод неверен, используя библиотеку Materialize (атрибут data-error). Таким образом, мой html-компонент выглядит следующим образом:

            <input
                    type="text"
                    id="username"
                    formControlName="username"
                    [class.valid]="username?.valid && username.dirty"
                    [class.invalid]="!username?.valid && username.dirty && !username.pending"
            >
            <label for="username"
                   data-error="ERROR_MESSAGE" // <-- this is what I need to work
            >Username</label>

Я хочу изменить атрибут data-error в зависимости от наличия ошибки. Прямо сейчас он будет печатать «ERROR_MESSAGE» на любой ошибке присутствует. Я попытался написать функцию и привязать ее к [attr.data-error] как это:

    displayUsernameErrorMessage() {
    let message = '';
    let usernameError = this.username.errors;
    if(usernameError.pattern){
        message = "Invalid Username"
        console.log(usernameError);
    }
    else {
        return null;
    }
}

I think i’m doing a really bad job with this, the function logs like 10 times in the console and it’s a poor solution. Любые идеи о том, как сделать его работать лучше, очень ценятся!

EDIT 1: дополнительная информация заключается в том, что я хочу отображать различные сообщения в зависимости от ошибки. Так что если я получу ошибку от валидатора.pattern — я хочу, чтобы сообщение было чем-то вроде «недопустимое имя пользователя» или если оно от валидаторов.требуется- «пожалуйста, введите имя пользователя», что-то вроде этого.

2 ответа

  1. Вот как я это делаю (адаптировано к вашему Exemple):

    <form name="nameForm" [formGroup]="nameForm">
    <fieldset>
            <label for="username">Username</label>
            <input
              required
              id="username"
              formControlName="username"
            >
            <span
              class="text-danger"
              [hidden]="nameForm.controls.name.valid || itemForm.controls.name.pristine"
            >
              <small>{{'Please enter your name'}}</small>
            </span>
          </fieldset>
    </form>
    

    В файле TS :

    import { FormGroup, FormBuilder, FormControl, Validators } from '@angular/forms';
    
    export class InputComponent  {   
       public nameForm: FormGroup;
      constructor(private formBuilder: FormBuilder) {
    
      this.nameForm = this.formBuilder.group({
      username:    new FormControl('', Validators.required),
       });
      }
    //... codes..
    }
    

    Где вы можете настроить text-dangerсвой CSS(или любой другой) файл

  2. Мне нужно было сделать что-то вроде этого, поэтому я написал директиву, которая может быть размещена на <label>элементах.

    В вашем примере это выглядело бы так:

    <label for="username" errorMessageForFormControl>Username</label>
    <input required id="username" formControlName="username">
    

    Я хотел избежать повторения имени элемента управления дважды, поэтому директива смотрит на значение forатрибута и находит элемент управления из него. Если ваши FormControls и <input>ID полей не совпадают, вы можете установить его самостоятельно.

    <label for="somethingDifferent" errorMessageForFormControl="username">Username</label>
    <input required id="somethingDifferent" formControlName="username">
    

    Директива выглядела так:

    import { Directive, Host, HostBinding, Input, Optional, OnInit, SkipSelf } from '@angular/core';
    import { AbstractControl, ControlContainer } from '@angular/forms';
    
    @Directive({
        selector: '[errorMessageForFormControl]'
    })
    export class errorMessageDirective implements OnInit {
        @HostBinding('class.validation-error') validationErrorCssClass = false;
        @HostBinding('attr.data-error') errorMessage: string = null;
    
        @Input() public errorMessageForFormControl: string;
        @Input() public for: string;
    
        private ctrl: AbstractControl = null;
    
        constructor(
            @Optional() @Host() @SkipSelf()
            private controlContainer: ControlContainer
        ) { }
    
        public ngOnInit(): void {
            if (!this.controlContainer) {
                return;
            }
    
            const formControlName = this.errorMessageForFormControl || this.for;
            if (formControlName) {
                this.ctrl = this.controlContainer.control.get(formControlName);
            }
    
            if (this.ctrl) {
                this.ctrl.statusChanges.subscribe(statusText => {
    
                    if (statusText === 'INVALID') {
                        // invalid
                        const errors = this.ctrl.errors;
                        if (errors) {
                            const errKey = Object.keys(errors)[0];
                            const errVal = errors[errKey];
                            this.errorMessage = errVal === true ? errKey : errVal;
                        } else {
                            this.errorMessage = 'validation failed';
                        }
    
                        this.validationErrorCssClass = true;
                    } else {
                        // valid
                        this.errorMessage = null;
                        this.validationErrorCssClass = false;
                    }
                });
            }
        }
    }
    

    И вы можете ссылаться на атрибут data-error в некоторых css

    [data-error].validation-error::after {
        color:red;
        content: attr(data-error);
        opacity: 0.8; 
        font-weight: bold;
        font-style: italic;
        font-size: 0.75em;
        margin-right: 0.25em;
        z-index: 99;
    
        float: right;
        transform: translateY(85%);
    }