>source

주어진 사용자 이름이 이미 존재하는지 확인하는 반응 양식 제어를위한 비동기 유효성 검사기를 만들려고합니다. 다음은 비동기 유효성 검사기 코드입니다.

userdata.service.ts

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { FormControl } from '@angular/forms';
import { Observable } from 'rxjs';
@Injectable({
  providedIn: 'root'
})
export class UserdataService {
   private apiUrl = 'http://apiurl.com/api'; // its not the real url, im just not posting it for privacy reasons
   constructor(private http: HttpClient) {}
   checkUsername(control: FormControl): Promise<any> | Observable<any> {
    let isUsernameValid;
    return new Promise<any>(
      (resolve, reject) => {
        this.http.get(this.apiUrl + '/users?name='+control.value).subscribe(
          response => {
            isUsernameValid = response;
        });
        if (isUsernameValid === 'false') {
          resolve({'usernameIsInvalid': true})
        } else {
          resolve(null);
        }
      }
    );
  }
}

이 유효성 검사기를 시도하면이 오류가 발생합니다. "core.js : 4197 오류 유형 오류 : 정의되지 않은 'http'속성을 읽을 수 없습니다."

자, 나는 errr이 'this'를 사용하는 것과 관련이 있다고 생각하지만 왜 작동하지 않는지 이해할 수 없습니다 ... 그것은 나를 미치게 만들었 기 때문에 나는

console.log(this.apiUrl)

함수 내부, 약속 외부, 시도하기 위해 동일한 오류가 발생했습니다. "core.js : 4197 ERROR TypeError : Cannot read property 'apiUrl'of undefined"...

누군가 내가 뭘 잘못하고 있는지 설명해 주시고 해결 방법을 알려 주시면 감사하겠습니다.

편집하다:

아래와 같이 반응 형 ts 파일에서 내 서비스를 호출합니다.

import { Component, OnInit } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { CustomValidatorsService } from '../services/custom-validators.service';
import { LocationService } from '../services/location.service';
import { UserdataService } from '../services/userdata.service';
@Component({
  selector: 'app-userdata-form',
  templateUrl: './userdata-form.component.html',
  styleUrls: ['./userdata-form.component.scss']
})
export class UserdataFormComponent implements OnInit {
  userdataForm: FormGroup;
  provinces: any = null;
  provincesLoading = false;
  cities: any = null;
  citiesLoading = false;
  constructor(
    private locationService: LocationService,
    private userdataService: UserdataService,
    private customValidators: CustomValidatorsService,
    private router: Router,
    private route: ActivatedRoute
    ) { }
  ngOnInit(): void {
    this.formInit();
    this.loadProvinces();
  }
  formInit() {
    let dni: number = null;
    let firstname: string = null;
    let lastname: string = null;
    let email: string = null;
    let mobile: number = null;
    let phone: number = null;
    let birthdate: Date = null;
    let username: string = null;
    let password: string = null;
    this.userdataForm = new FormGroup({
        // ... a lot of controls before ...
        'username': new FormControl(username, [
          Validators.required,
          Validators.minLength(3),
          Validators.maxLength(30),
          Validators.pattern(/^[a-zA-ZÀ-ÿ\u00f1\u00d1]+(\s*[a-zA-ZÀ-ÿ\u00f1\u00d1]*)*[a-zA-ZÀ-ÿ\u00f1\u00d1]+$/)
        ], this.userdataService.checkUsername), // <-- here's the async validator
        // ... form continues...
  }
  loadProvinces() {
    this.provincesLoading = true;
    this.locationService.getProvinces().subscribe(response => {
      this.provinces = response;
      this.provincesLoading = false;
    });
  }


  • 답변 # 1

    주석에서 언급했듯이 사용자 지정 유효성 검사기는 서비스가 아니어야합니다. 대신 클래스를 AsyncValidator 상호 작용:

    import { AbstractControl, AsyncValidator, ValidationErrors } from '@angular/forms';
    import { catchError, map } from 'rxjs/operators';
    // ...
    @Injectable({
      providedIn: 'root'
    })
    export class UserDataValidator implements AsyncValidator {
      private apiUrl = 'http://apiurl.com/api'; // its not the real url, im just not posting it for privacy reasons
      constructor(private http: HttpClient) {}
      // This method is defined as an arrow function such that it can be used
      // properly - see https://github.com/angular/angular/issues/24981
      validate = (control: AbstractControl) => {
        return this.http.get(`${this.apiUrl}/users?name=${control.value}`).pipe(
          map(isUsernameValid => (isUsernameValid === 'false' ? { usernameIsInvalid: true } : null),
          catchError(() => of(null))
        );
      }
    }
    
    

    그런 다음 귀하의 FormGroup 다음과 같이 :

    constructor (private userDataValidator: UserDataValidator) {
      this.userdataForm = new FormGroup({
        username: new FormControl(username, [
          // ... validators
          // Validator classes don't currently work - see
          // https://github.com/angular/angular/issues/24981
          this.userDataValidator.validate
        ]),
        // ... other form controls
    }
    // ...
    
    
    <시간 /> 메모

    또한 RxJS의 파이프 가능 연산자를 사용하고 템플릿 리터럴을 사용하는 유효성 검사 논리를 수행하는 코드를 정리했습니다.)

    면책 조항 : 위 코드가 실제로 작동하는지 테스트하지 않았습니다.

    <시간 /> 자원

    Angular-양식 입력 유효성 검사>비동기 유효성 검사기 만들기

    유효성 검사기 클래스를 FormControl 생성자에 전달할 수 있음 · 문제 # 24981 · 각도/각도

  • 답변 # 2

    이 기사에서와 같이 서비스 인스턴스를 인수로 가져 오는 유효성 검사기 함수를 만들어야한다고 생각합니다. https://medium.com/@tomaszsochacki/how-to-do-asynchronous-validator-in-angular-7-6e80243a874a

    이와 같은 방법을 전달할 때

    'username': new FormControl(username, [
              Validators.required,
              Validators.minLength(3),
              Validators.maxLength(30),
              Validators.pattern(/^[a-zA-ZÀ-ÿ\u00f1\u00d1]+(\s*[a-zA-ZÀ-ÿ\u00f1\u00d1]*)*[a-zA-ZÀ-ÿ\u00f1\u00d1]+$/)
            ], this.userdataService.checkUsername),
    
    

    this checkUsername 메소드의 컨텍스트가 누락되었습니다.

    또는 다음을 수행 할 수 있습니다.

    'username': new FormControl(username, [
              Validators.required,
              Validators.minLength(3),
              Validators.maxLength(30),
              Validators.pattern(/^[a-zA-ZÀ-ÿ\u00f1\u00d1]+(\s*[a-zA-ZÀ-ÿ\u00f1\u00d1]*)*[a-zA-ZÀ-ÿ\u00f1\u00d1]+$/)
            ], this.userdataService.checkUsername.bind(this.userdataService)),
    
    

    첫 번째 인수에 바인딩이 호출되면 'this'컨텍스트를 메소드에 전달합니다.

관련 자료

  • 이전 Python If Statements - python if 문 - 숫자 결과 표시
  • 다음 jquery - 입력 값에 따라 제출 버튼을 비활성화 및 활성화하는 방법