javascript - 自定义验证器无法访问 Angular 6 Reactive 表单中的表单

标签 javascript angular typescript validation

我正在尝试为 Angular react 形式创建一个验证密码验证,但不断返回 无法读取未定义的属性“get” 控制台出错,我不知道出了什么问题

我尝试以各种方式访问​​密码字段,但只是得到不同类型的“无法访问,不存在”错误

这是 Ts 代码:

import { Component, OnInit, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { NgForm, FormsModule, FormGroup, FormControl, Validators } from '@angular/forms';
import { ApartmentService } from '../apartments/apartment.service';
import { Apartment } from '../apartments/apartment.model';

@Component({
  selector: 'app-signup',
  templateUrl: './signup.component.html',
  styleUrls: ['./signup.component.css']
})
export class SignupComponent implements OnInit, AfterViewInit {
  @ViewChild('terms') terms: ElementRef ;
  
  signupForm: FormGroup;

  constructor(private apartmentService: ApartmentService) { }
  date: Date = new Date();  

  // Used to set maxdate to current date
  maxDate = (new Date().getFullYear()).toString()+"-0"+(new Date().getMonth()+1).toString()+"-"+(new Date().getDate()).toString();
  
  ngOnInit() {
    this.signupForm = new FormGroup({
      'firstName': new FormControl(null, Validators.required),
      'lastName': new FormControl(null, Validators.required),
      'email': new FormControl(null, [Validators.required, Validators.email]),
      'passwordFields': new FormGroup({
        'password': new FormControl(null, Validators.required),
        'verifyPassword': new FormControl(null, [Validators.required, this.passwordMatchFail.bind(this)]),
      }),
      'birthdate': new FormControl(null),
      'flatPurchaceDate': new FormControl(null, Validators.required),
      'profilePicture': new FormControl(null),
      'flatDetails': new FormGroup({
        'flatBlock': new FormControl(null, Validators.required),
        'flatNumber': new FormControl(null, Validators.required)
      }),
      'mobileNumber': new FormControl(null, Validators.required),
      'terms': new FormControl(null)
    });
  }

  // terms validation
  ngAfterViewInit() {
    var termsAccepted = this.terms.nativeElement.checked;
    console.log(termsAccepted);
  }
  
  onSubmit(form: NgForm) {
    console.log(form)
    const firstName: string = form.value.firstName;
    const lastName: string = form.value.lastName;
    const flatBlock: string = form.value.flatDetails.flatBlock;
    const flatNumber: string = form.value.flatDetails.flatNumber;
    const email: string = form.value.email;
    
    var newApartment = {
      fBlock: flatBlock,
      fNumber: flatNumber,
      oName: firstName
    }
    this.apartmentService.addApartment(newApartment)
    console.log("Apt ADd")
    console.log(newApartment);
  }
  

  passwordMatchFail(control: FormControl): {[s: string]: boolean} {
    if(this.signupForm.get('passwordFields.password').value !== control.value) {
      return {'passwordMatchFail': true};
    }
    return null;
  }
}

HTML 代码:

<div class="row main-c">
  <div class="col-xs-8 col-xs-offset-2">
    
    
    <form [formGroup]="signupForm" (ngSubmit)="onSubmit()" >      
      <div class="row">
        <div class="col-xs-6">

          <!-- FIRST NAME -->
          <div class="form-group">
            <input 
            placeholder="First Name"
            required
            formControlName="firstName"
            pattern="[a-zA-Z]+"
            maxlength="50"
            class="form-control"
            type="text" name="firstName" id="fname">
          </div>
          <span class="help-block"
          *ngIf="!signupForm.get('firstName').valid && signupForm.get('firstName').touched"
          >This field is required</span>
        </div>

        <!-- LAST NAME -->
        <div class="col-xs-6">
          <div class="form-group">
            <input 
            placeholder="Last Name"
            formControlName="lastName"
            required
            pattern="[a-zA-Z]+"
            maxlength="50"
            class="form-control"
            type="text" name="lastName" id="lastName">
          </div>
          <span class="help-block"
          *ngIf="!signupForm.get('lastName').valid && signupForm.get('lastName').touched"
          >This field is required</span>
        </div>
      </div>
      
      <!-- EMAIL -->
      <div class="form-group">
        <input 
        placeholder="<a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="6811071d1a280d05090104460b0705" rel="noreferrer noopener nofollow">[email protected]</a>"
        formControlName="email"        
        required
        email
        class="form-control"
        type="email" name="email" id="email">
      </div>
      <span class="help-block"
      *ngIf="!signupForm.get('email').valid && signupForm.get('email').touched"
      >Please enter a valid email</span>
      
      <!-- PASSWORD FIELDS -->

      <div
      formGroupName="passwordFields"
      class="password-fields">
        <!-- PASSWORD -->
      <div class="form-group">
        <input
        formControlName="password"        
        placeholder="Password"
        required
        pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{6,}"
        class="form-control"
        type="password" name="password" id="password">
      </div>
      <span class="help-block"
      *ngIf="!signupForm.passwordFields.get('password').valid && signupForm.passwordFields.get('password').touched"
      >Please enter a valid password, password must be 8 characters long and contain 1 number, 1 special charactrer and 1 uppercase letter.</span>
      
      <!-- CONFIRM PASSWORD -->
      <div class="form-group">
        <input 
        placeholder="Confirm Password"
        formControlName="verifyPassword"        
        class="form-control"
        type="password" name="verifyPassword" id="verifyPassword">
      </div>
      <span class="help-block"
      *ngIf="!signupForm.passwordFields.get('verifyPassword').valid && signupForm.passwordFields.get('verifyPassword').touched"
      >Passwords do not match</span>
      </div>
      
      
      <!-- BIRTHDAY -->
      <div class="row">
        <div class="col-xs-6">
          <div class="form-group">
            <input 
            formControlName="birthdate"
            [max]="maxDate"
            class="form-control"
            placeholder="Birth Date"
            type="date" name="birthdate" id="birthdate">
          </div>
        </div>

        <!-- FLAT PURCHACE DATE -->
        <div class="col-xs-6">
          <div class="form-group">
            <input 
            required
            formControlName="flatPurchaceDate"
            placeholder="Flat Purchace date"
            [max]="maxDate"
            class="form-control date"
            type="date" name="flatPurchaceDate" id="flatPurchaceDate">
          </div>
          <span class="help-block"
          *ngIf="!signupForm.get('flatPurchaceDate').valid && signupForm.get('flatPurchaceDate').touched"
          >Please select a purchace date</span>

          
        </div>
        
      </div>
      <!-- PROFILE PICTURE -->
      <div class="form-group">
        <label for="proficePicture">Profile Picture</label>
        <input 
        formControlName="profilePicture"
        class="form-control-file"
        size="60"
        type="file" name="profilePicture" id="profilePicture" >
      </div>
      
      <!-- FLAT DETAILS -->
      <div class="flat-details" 
      formGroupName="flatDetails"
      >
      <!-- Flat Block -->
          <div class="row">
              <div class="col-xs-2">
                <div class="form-group">
                  <label for="flatBlock">Flat Block</label>
                  <select 
                  required
                  class="form-control"
                  id="flatBlock" name="flatBlock">
                  <option selected value="A">A</option>
                  <option value="B">B</option>
                </select> 
              </div>
            </div>
      <!-- Flat Number -->
            <div class="col-xs-2">
              <div class="form-group">
                <label for="flatNumber">Flat Number</label>
                <input 
                required
                placeholder="1"
                min="1" max="10"
                class="form-control"
                type="number" name="flatNumber" id="flatNumber">
              </div>
            </div>
      
          </div>
      </div>
      <!-- Help Block -->
      <!-- EDIT -->
    <span class="help-block"
        *ngIf="!signupForm.get('flatDetails').valid && signupForm.get('flatDetails').touched"
        >Please choose a valid flat block and number</span> 
      
    
    <!-- MOBILE NUMBER -->
    <div class="form-group">
      <label for="mobileNumber">Mobile Number</label>
      <input 
      required
      pattern="[1-9]{1}[0-9]{11}"
      placeholder="12 Digits Including Country code"
      maxlength="12"
      class="form-control"
      type="tel" name="mobileNumber" id="mobileNumber">
    </div>
    <span class="help-block"
        *ngIf="!signupForm.get('mobileNumber').valid && signupForm.get('mobileNumber').touched"
        >Please enter a valid 12 digit contact number</span>
    
        <!-- TERMA AGREEMENT -->
    <div class="form-group">
      <div class="">
        <input
        required
        class=""
        type="checkbox" #terms id="terms" name="terms">
        <label id="checkbox-label" for="terms" class="">I agree to terms and Conditions </label>          
      </div>
    </div>
    
    <!-- terms accepted to allow t&c checked requirement -->
    <button [disabled]="!signupForm.valid && !termsAccepted" class="btn btn-primary">Sign Up</button>
  </form>
  <br>
  <a routerLink="">Forgot Password</a>

  
  <br><br><br><br><br>

</div>
</div>

最佳答案

您的代码可以简化如下。使用 FormBuilder 创建“FormGroup”实例。并将自定义验证器添加到表单组中。

component.ts

import { Component } from '@angular/core';
import {
  FormBuilder,
  FormGroup,
  ValidationErrors,
  ValidatorFn,
  Validators
} from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public registerForm: FormGroup;


  constructor(private fb: FormBuilder) {
    this.buildRegisterForm();
  }

  private buildRegisterForm(): void {
    this.registerForm = this.fb.group(
      {
        email: [
          null,
          Validators.compose([Validators.required, Validators.email])
        ],
        password: [null, Validators.required],
        confirmPassword: [null, Validators.required]
      },
      { validator: this.passwordValidator() }
    );
  }

  private passwordValidator(): ValidatorFn {
    return (group: FormGroup): ValidationErrors => {
      const password = group.controls['password'];
      const confirmPassword = group.controls['confirmPassword'];
      if (password.value !== confirmPassword.value) {
        confirmPassword.setErrors({ notEquivalent: true });
      } else {
        confirmPassword.setErrors(null);
      }
      return;
    };
  }
}

component.html

<form class="register-frm frm " [formGroup]="registerForm" (ngSubmit)="onRegisterSubmit()" *ngIf="!isLoginTab">
    <div class="form-group">
        <label for="email2">Email:</label>
        <input type="email" required name="email" autocomplete="email" id="email2" formControlName="email">
    </div>
    <div class="form-group">
        <label for="pass3">Password:</label>
        <input type="password" required name="password" id="pass3" formControlName="password">
    </div>
    <div class="form-group">
        <label for="pass2">Confirm Password:</label>
        <input type="password" required name="password" id="pass2" formControlName="confirmPassword">
        <div *ngIf="registerForm.get('confirmPassword')?.errors?.notEquivalent">
            Passwords do not match
        </div>
    </div>
    <div class="sub-btn">
        <input type="submit" class="btn ui-btn info" value="REGISTER" [disabled]="registerForm.invalid">
    </div>
</form>.

可以在 stackblitz 中找到一个工作示例。 .

关于javascript - 自定义验证器无法访问 Angular 6 Reactive 表单中的表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51130218/

相关文章:

javascript - 使用 jquery 获取 span 元素之后的文本,不包括 span 之前的文本

javascript - 在 node-mysql 中使用 SSH 隧道连接到 MySQL

javascript - 使用 TypeScript

javascript - 在 jQuery 中,你能得到正在褪色的元素的 "target"不透明度吗?

javascript - 滚动底部隐藏的 div

javascript - RxJS 6 获取 Observable 数组的过滤列表

Angular 4-如何将 POST 中的文件发送到后端

javascript - MatSelect 打开时如何滚动底层 MatDialog?

Angular 2 单元测试服务 stub 值不会改变?

javascript - ASP.NET Core 3.0 MVC 连接中的 SignalR 保持事件状态不起作用?