微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用服务创建自定义表单验证器?

如何解决如何使用服务创建自定义表单验证器?

我为自定义表单验证器创建了可注射服务:

    import { Injectable } from '@angular/core'
    import { FormControl } from '@angular/forms'
    import { Observable,of,timer } from 'rxjs'
    import { map,switchMap } from 'rxjs/operators'
    
    @Injectable({
      providedIn: 'root'
    })
    export class IsValidNicknameService {
    
      validate = (time: number = 500) => {
        return (input: FormControl) => {
          return timer(time).pipe(
            switchMap(() => this.isValidNickname(input.value)),map(isValid => {
              return isValid ? null : { shouldNotStartWithA: true }
            })
          )
        }
      }
    
      private isValidNickname(value: string): Observable<boolean> {
        return this.checkIfFirstLetterIsA(value)
      }
    
      private checkIfFirstLetterIsA(value: string): Observable<boolean> {
        const firstCharacter = value.toLowerCase().charat(0)
        if (firstCharacter === 'a' || firstCharacter === 'à' || firstCharacter === 'ä' || firstCharacter === 'á' || firstCharacter === 'ã') {
          return of(false)
        } else {
          return of(true)
        }
      }
    
    }

然后我在控制器中这样称呼它:

    import { IsValidNicknameService } from './src/Core/Services/isvalidnickname.service'
    createNicknamesGroup(): any {
      return new FormGroup({
        buildingRoom: new FormControl(this.mockBuildingRooms[0],Validators.required),nickname: new FormControl('',Validators.required,this.isValidNicknameService.validate())
      })
    }

它有效,但是我觉得这不是一个方法。有没有更好,更简洁的方法来实现这一目标?

解决方法

这里没有正确或错误的方法-做任何适合您的事情。

从您的代码开始-您没有任何服务依赖关系,因此您的服务可以轻松转换为一堆函数。使用普通函数的一个优点是可以轻松地用单元测试覆盖它们。

通常来说,如果需要通过Angular的DI向构造函数中注入某些依赖项,则需要使用@Injectable()类。但这也可以通过将必要的依赖项传递给您的验证器higher order function来避免:

# my-custom.validator.ts

export const setupRequiredValidator(minLength: number,someCheckerService: CheckerService): ValidatorFn => {
 return (control: AbstractControl) => {
   return control.value.length >= minLength && someCheckerService.check(control);
 }
}
# my.component.ts

constructor(private someCheckerService: CheckerService) {
}

createNicknamesGroup(): FormGroup {
  return new FormGroup({
      buildingRoom: new FormControl(this.mockBuildingRooms[0],Validators.required),nickname: new FormControl('',[Validators.required,setupRequiredValidator(5,this.someCheckerService)])
    }) // an example of synchronous validator
  }

您还可以创建@Injectable()验证程序,不要将其称为Service-没有人会对您发誓。

# my-custom.validator.ts

@Injectable({
 providedIn: 'root'
})
export class MyCustomValidator {
  constructor(private router: Router) {}

  validateName = (control: AbstractControl) => {
    // try to do only one validation per method if there are no dependencies between the validators. 
    // It's easier to combine and tests them afterwards
    return control.value ? null : {error: 'text'};
  }

  validateEmail = (control: AbstractControl) => {
    return control.value ? Validators.email(control) : null;
  }

  validateSurnameIfTheNameExists = (control: AbstractControl) => {
    return control.parent.get('name').valid ? null : this.router.navigate(['/error']);
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。