如何动态创建验证器并绑定到表单组?

时间:2018-10-24 16:57:48

标签: angular typescript rxjs

目前,我正在与一个提供rest api的java后端一起在一个有角项目中工作。我想发出一个REST API调用,然后获取一个object,然后将其传递给自定义验证器函数,然后在表单组中使用此验证器。但是,由于使用了RxJ,因此无法正常工作

这是我从Angular js进行的api调用

@Injectable()
export class ModeService {
  get() {
    return this.httpClient
      .get<Mode>(`${this.config.api}/configuredMode`)
      .pipe(shareReplay(1));
  }
}

我的角度分量如下

export class AccountFormComponent implements OnInit {
     ngOnInit() {
    this.modeService.get().subscribe(
      mode => {
        this.mode = mode;
        this.isConfigurationLoading = false;
        this.emailValidator = emailDomainValidator(this.mode);
      },
      () => {
        this.isConfigurationLoading = false;
      }
    );

    this.formGroup = this.fb.group({
      internal: [
        { value: true, disabled: !this.isTypeEditable },
        [Validators.required]
      ],
      name: ['', [Validators.required]],
      firstName: [
        { value: '', disabled: !this.showAdminFields },
        [Validators.required]
      ],
      lastName: [
        { value: '', disabled: !this.showAdminFields },
        [Validators.required]
      ],
      email: [
        { value: '', disabled: !this.showAdminFields },
        [Validators.required, Validators.email, this.emailValidator]
      ]
}

我的模板如下

> <form novalidate [formGroup]="formGroup"
> (ngSubmit)="handleSubmit(formGroup.value)" class="mb-3"
> *ngIf="(!isLoading && !isConfigurationLoading)">   <pc-form-layout>
> 
> </form>

和我的验证器功能

export function emailDomainValidator(configuredMode: Mode): ValidatorFn {
  return (control: AbstractControl): { [key: string]: boolean } | null => {
    if (configuredMode.propositionType === PropositionType.CMS) {
      const emailId: string = control.value;
      const emailDomain: string = configuredMode.emailDomain;
      if (!emailId.endsWith(emailDomain)) {
        return { invalidEmail: true };
      }
      return null;
    }
    return null;
  };
}

但是,当我访问从chrome开发人员控制台获取的应用程序时出现错误。我能确定的是在emailDomainValidator中,configureMode是未定义的,并且在调用propositionType时遇到了这个问题。

VM30160 AccountFormComponent.ngfactory.js:1312 ERROR TypeError: Cannot read property 'propositionType' of undefined
    at Object.eval [as updateRenderer] (VM30160 AccountFormComponent.ngfactory.js:1323)
    at Object.debugUpdateRenderer [as updateRenderer] (VM28852 core.js:14891)
    at checkAndUpdateView (VM28852 core.js:14005)
    at callViewAction (VM28852 core.js:14351)
    at execComponentViewsAction (VM28852 core.js:14283)
    at checkAndUpdateView (VM28852 core.js:14006)
    at callViewAction (VM28852 core.js:14351)
    at execEmbeddedViewsAction (VM28852 core.js:14309)
    at checkAndUpdateView (VM28852 core.js:14001)
    at callViewAction (VM28852 core.js:14351)

任何想法如何解决此问题???感谢您的帮助,非常感谢

1 个答案:

答案 0 :(得分:1)

它将在收到响应(API请求)后创建FormGroup

export class AccountFormComponent implements OnInit {
    ngOnInit() {
        this.modeService.get().subscribe(
            mode => {
                this.mode = mode;
                this.isConfigurationLoading = false;

                this.createForm();
            },
            () => {
                this.isConfigurationLoading = false;
            }
        );
    }

    private createForm() {
        this.formGroup = this.fb.group({
            internal: [
                {value: true, disabled: !this.isTypeEditable},
                [Validators.required]
            ],
            name: ['', [Validators.required]],
            firstName: [
                {value: '', disabled: !this.showAdminFields},
                [Validators.required]
            ],
            lastName: [
                {value: '', disabled: !this.showAdminFields},
                [Validators.required]
            ],
            email: [
                {value: '', disabled: !this.showAdminFields},
                [Validators.required, Validators.email, emailDomainValidator(this.mode)]
            ]
        });
    }
}

如果您要先创建FormGroup,然后在响应到达时更新验证器,则可以尝试以下操作:

export class AccountFormComponent implements OnInit {
    ngOnInit() {
        this.formGroup = this.fb.group({
            internal: [
                {value: true, disabled: !this.isTypeEditable},
                [Validators.required]
            ],
            name: ['', [Validators.required]],
            firstName: [
                {value: '', disabled: !this.showAdminFields},
                [Validators.required]
            ],
            lastName: [
                {value: '', disabled: !this.showAdminFields},
                [Validators.required]
            ],
            email: [
                {value: '', disabled: !this.showAdminFields},
                [Validators.required, Validators.email]
            ]
        });

        this.modeService.get().subscribe(
            mode => {
                this.mode = mode;
                this.isConfigurationLoading = false;

                this.formGroup.controls.email.setValidators([
                    Validators.required,
                    Validators.email,
                    emailDomainValidator(this.mode)
                ]);
                this.formGroup.controls.email.updateValueAndValidity();
            },
            () => {
                this.isConfigurationLoading = false;
            }
        );
    }
}