Angular 2+, почему материал не хочет показывать сообщение об ошибке? - PullRequest
0 голосов
/ 09 октября 2019

Я хочу подтвердить пароли, но когда я написал логику валидатора и отправил его на mat-error, сообщение не показывалось, но валидатор работает нормально, как исправить этот момент в реактивных формах в моем случае? ?

export class SignUpComponent implements OnInit {

  profileForm: FormGroup;

  constructor(
     private userService: UserService,
     private formBuilder: FormBuilder
  ) {
    this.profileForm = this.formBuilder.group({
      name: ['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9_ -]+$/)]],
      email: ['', [Validators.required, Validators.pattern(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)]],
  password: ['', [Validators.required, Validators.pattern(/^(?=.*[A-Z])(?=.*\d)(.{8,100})$/)]],
      passwordConfirm: ['', [Validators.required]]
    },
      { validator: this.checkPasswords }
    );
  }

  checkPasswords(group: FormGroup) {
    let pass = group.get('password').value;
    let confirmPass = group.get('passwordConfirm').value;

    return pass === confirmPass ? null : { mismatch: true }     
  }   

  ngOnInit() {
  }

  get name(){
    return this.profileForm.get('name');
  }

  get email(){
    return this.profileForm.get('email');
  }

  get password(){
    return this.profileForm.get('password')
  }

  get passwordConfirm(){
    return this.profileForm.get('passwordConfirm')
  }

  onSubmit() {
    console.warn(this.profileForm.value);
    this.userService.createUser(this.profileForm.value);    
  }

}

в html-коде

<form class="form-to-submit" [formGroup]="profileForm" (ngSubmit)="onSubmit()">

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput placeholder="Name" formControlName="name" required> 
                <mat-icon matSuffix>supervised_user_circle</mat-icon>

                <mat-error *ngIf="name.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>
                <mat-error *ngIf="name.hasError('pattern')">
                    Field should use <strong>Latin alphabet</strong> 
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput placeholder="Email" formControlName="email" required>
                <mat-icon matSuffix>email</mat-icon> 

                <mat-error *ngIf="email.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>
                <mat-error *ngIf="email.hasError('pattern')">
                    Use right <strong>email format</strong> 
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput type="password" placeholder="Password" formControlName="password" required> 
                <mat-icon matSuffix>lock</mat-icon>

                <mat-error *ngIf="password.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>
                <mat-error *ngIf="password.hasError('pattern')">
                    Should be <strong>minimum 8 elements, one uppercase letter, one number</strong> 
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-position">
            <mat-form-field class="example-full-width"  >
                <input matInput type="password" placeholder="Confirm password" formControlName="passwordConfirm" required> 
                <mat-icon matSuffix>lock</mat-icon>

                <mat-error *ngIf="passwordConfirm.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>

                {{profileForm.hasError('mismatch')}}
                <mat-error *ngIf="profileForm.hasError('mismatch')">
                    Password <strong>mistmached</strong>
                </mat-error>

            </mat-form-field>
        </div>

        <div class="form-input-button">
            <button mat-raised-button color="accent" [disabled]="!profileForm.valid" type="submit">Submit</button>
            <button mat-raised-button color="warn">Cancel</button>
        </div>


    </form>

в этом случае я пытался ( Подтвердить проверку пароля в решении Angular 6 ), но проблема в ошибке:

Uncaught Error: неожиданное значение SignUpComponent, объявленное модулем AppModule. Пожалуйста, добавьте аннотацию @ Pipe / @ Directive / @ Component.

и, если я прав, это template-driven forms нереактивный способ

Узел

мой app.modul.ts файл

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { SignUpComponent } from './sign-up/sign-up.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';

import { MatIconModule,
     MatMenuModule,
     MatInputModule,
     MatButtonModule
     } from '@angular/material';
import { LoginComponent } from './login/login.component';
import { HomeComponent } from './home/home.component';

@NgModule({
  declarations: [
AppComponent,
SignUpComponent,
LoginComponent,
HomeComponent
  ],
  imports: [
BrowserModule,
FormsModule,
AppRoutingModule,
BrowserAnimationsModule,
MatMenuModule,
MatIconModule,
MatInputModule,
MatButtonModule,
ReactiveFormsModule,    
HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Узел 2

Я прочитал https://itnext.io/materror-cross-field-validators-in-angular-material-7-97053b2ed0cf

и этот https://material.angular.io/components/input/overview#changing-when-error-messages-are-shown

эта ссылка рассказала о реализации ErrorStateMatcher для касания ввода. Ну, я изменил свой код

в sign-up.component.ts

export class MyErrorStateMatcher implements ErrorStateMatcher {
   isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
  return control.dirty && form.invalid;
  }
}

Если мы начали вводить что-то во ввод, а сама форма недействительна, заявите, чтоэлемент управления имеет ошибки.

создайте объект errorMatcher = new MyErrorStateMatcher(); при входе в систему class SignUpComponent

моя форма в файле ts выглядит как

this.profileForm = this.formBuilder.group({
  name: ['', [Validators.required, Validators.pattern(/^[a-zA-Z0-9_ -]+$/)]],
  email: ['', [Validators.required, Validators.pattern(/^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)]],
  password: ['', [Validators.required, Validators.pattern(/^(?=.*[A-Z])(?=.*\d)(.{8,100})$/)]],
  passwordConfirm: ['']
},
  { validator: this.passwordValidator }
);
}

passwordValidator(form: FormGroup) {
  const condition = form.get('password').value !== form.get('verifyPassword').value;

  return condition ? { passwordsDoNotMatch: true} : null;
}

и, наконец, htmlfile

<input matInput type="password" placeholder="Confirm password" formControlName="passwordConfirm" required
                       [errorStateMatcher]="matcher"> 
                <mat-icon matSuffix>lock</mat-icon>

                <mat-error *ngIf="passwordConfirm.hasError('required')">
                    Field should be <strong>required</strong>
                </mat-error>

                {{profileForm.hasError('mismatch')}}
                <mat-error 
*ngIf="profileForm.hasError('passwordsDoNotMatch')">
                    Field should be <strong>AAAAA</strong>
                </mat-error>
                <p 
*ngIf="profileForm.hasError('passwordsDoNotMatch')">aaaaaaaaaaaaaaaa</p>

Однако у меня есть большая проблема, которая останавливает загрузку формы

compiler.js: 2175 Uncaught Ошибка: неожиданное значение SignUpComponent, объявленное модулем AppModule,Пожалуйста, добавьте аннотацию @ Pipe / @ Directive / @ Component.

Я пытался это исправить (добавьте в @NgModule следующие строки)

 providers: [
{ provide: ErrorStateMatcher, useClass: ShowOnDirtyErrorStateMatcher }
 ],

, но это не такмне помочь

1 Ответ

0 голосов
/ 09 октября 2019

* Обновление

Чтобы создать customFormControl поверх элемента управления, мы используем parent, см. Пример

checkPasswords(): ValidatorFn {
    //see that the argument is a FormControl
    return (control: FormControl): ValidationErrors => {
      //the formGroup is control.parent
      const group = control.parent as FormGroup;
      //but we must sure that is defined
      if (!group) return null;
      console.log(group.get("password").value);
      let pass = group.get("password").value;
      let confirmPass = group.get("passwordConfirm").value;

      return confirmPass ? pass === confirmPass ? null : { mismatch: true } : null;
    };
  }

Как мы хотим проверить при смене паролятоже

ngOnInit() {
    this.form.get("password").valueChanges.subscribe(() => {
      this.form.get("passwordConfirm").updateValueAndValidity();
    });
  }

Видите, что форма похожа на

form = new FormGroup({
    password: new FormControl("", Validators.required),
    passwordConfirm: new FormControl("", [
      Validators.required,
      this.checkPasswords()
    ])
  });

И .html

<form [formGroup]="form" class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="password" formControlName="password">
        <mat-error >
      required
    </mat-error>

  </mat-form-field>
  <mat-form-field class="example-full-width">
    <input matInput placeholder="repeat password" formControlName="passwordConfirm"
           >
    <mat-error *ngIf="form.get('passwordConfirm').hasError('mismatch')">
      must matcher
    </mat-error>
    <mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
      required
    </mat-error>
  </mat-form-field>
</form>

стекаблиц здесь

Другой способ - использовать пользовательский errorStateMatcher

Обновление 2 Я сказал, что другим способом является «использовать errorStateMatcher». ErroStateMatcher - это простая функция, которая возвращает true или false. Если вернуть true, наш элемент управления будет помечен, как если бы он был недействительным (*)

Представьте, что у нас есть форма, подобная

form = new FormGroup({
    password: new FormControl("", Validators.required),
    passwordConfirm: new FormControl("", [
      Validators.required,

    ])
  },this.checkPasswords());

Убедитесь, что ошибка принадлежит formGroup, мы можем создатьcustomErrorMatcher, которые возвращают true, если элемент управления недействителен или если form.hasError ('mismatch`)

export class MyErrorStateMatcher implements ErrorStateMatcher {
  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {
    return !!((control && form.hasError('mismatch') || control.invalid) && control.touched );
  }
}

.html

<form [formGroup]="form" class="example-form">
  <mat-form-field class="example-full-width">
    <input matInput placeholder="password" formControlName="password">
        <mat-error >
      required
    </mat-error>

  </mat-form-field>
<!--see that the "errorStateMatcher" is applied to the input "passwordConfirm"-->
  <mat-form-field class="example-full-width">
    <input matInput placeholder="repeat password" formControlName="passwordConfirm"
    [errorStateMatcher]="matcher"
           >
      <!--here show the error is form.hasError('mismatch')-->
    <mat-error *ngIf="form.hasError('mismatch')">
      must matcher
    </mat-error>
       <!--here show the error is form.get('passwordConfirm').hasError-->
    <mat-error *ngIf="form.get('passwordConfirm').hasError('required')">
      required
    </mat-error>
  </mat-form-field>
</form>

Как всегда, stackblitz

(*) отметьте в форме stackblitz form.get ('passwordConfirm'). invalid

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...