javascript - Angular:尝试添加验证码。错误 => 没有名称为 'captcha' 的表单控件的值访问器

标签 javascript angular captcha

因此,我遵循了有关如何将验证码添加到表单以防止垃圾邮件的教程。我按照所有步骤操作,但仍然收到以下错误:

 error inside log Error: No value accessor for form control with name: 'captcha'
    at _throwError (forms.js:2139)
    at setUpControl (forms.js:2008)
    at FormGroupDirective.addControl (forms.js:5144)
    at FormControlName._setUpControl (forms.js:5743)
    at FormControlName.ngOnChanges (forms.js:5684)
    at checkAndUpdateDirectiveInline (core.js:11642)
    at checkAndUpdateNodeInline (core.js:13252)

我有一个响应式(Reactive)注册表单,其中包含以下应该是验证码和 formControl 的元素。但不幸的是我什么也没看到。

<div nbRecaptcha key="6LfNfHYUAAAAAFaa7dVi2au1tnfod-2eR3Rb2enM" formControlName="captcha"></div>

这是 nbRecaptcha 指令:

declare const grecaptcha: any;

declare global {
  interface Window {
    grecaptcha: any;
    reCaptchaLoad: () => void
  }
}

@Directive({
  selector: '[nbRecaptcha]',
  providers: [ReCaptchaAsyncValidator]
})
export class RecaptchaDirective implements OnInit, ControlValueAccessor, AfterViewInit {
  @Input() key: string;
  @Input() config: ReCaptchaConfig = {};
  @Input() lang: string;

  private control: FormControl;

  private onChange: ( value: string ) => void;
  private onTouched: ( value: string ) => void;
  private widgetId: number;

  constructor(
    private element: ElementRef,
    private ngZone: NgZone,
    private injector: Injector,
    private reCaptchaAsyncValidator: ReCaptchaAsyncValidator){}

  ngOnInit() {
    this.registerReCaptchaCallback();
    this.addScript();
  }

  ngAfterViewInit() {
    this.control = this.injector.get(NgControl).control;
    this.setValidator();
  }

  addScript() {
    let script = document.createElement('script');
    const lang = this.lang ? '&hl=' + this.lang : '';
    script.src = `https://www.google.com/recaptcha/api.js?onload=reCaptchaLoad&render=explicit${lang}`;
    script.async = true;
    script.defer = true;
    document.body.appendChild(script);
  }


  //  We need to notify the formControl that it’s valid if we get the token
  // from the onSuccess function or that it’s invalid if the onExpired function is called.

  onExpired() {
    this.ngZone.run(() => {
      this.onChange(null);
      this.onTouched(null);
    });
  }

  onSuccess( token: string ) {
    this.ngZone.run(() => {
      this.verifyToken(token);
      this.onChange(token);
      this.onTouched(token);
    });
  }

  //  these are the three methods that controlValueAccessor requires

  writeValue( obj: any ): void {
  }

  registerOnChange( fn: any ): void {
    this.onChange = fn;
  }

  registerOnTouched( fn: any ): void {
    this.onTouched = fn;
  }

  private setValidator() {
    this.control.setValidators(Validators.required);
    this.control.updateValueAndValidity();
  }

  registerReCaptchaCallback() {
    window.reCaptchaLoad = () => {
      const config = {
        ...this.config,
        'sitekey': this.key,
        'callback': this.onSuccess.bind(this),
        'expired-callback': this.onExpired.bind(this)
      };
      this.widgetId = this.render(this.element.nativeElement, config);
    };
  }

  private render( element: HTMLElement, config ): number {
    return grecaptcha.render(element, config);
  }

  verifyToken( token : string ) {
    this.control.setAsyncValidators(this.reCaptchaAsyncValidator.validateToken(token))
    this.control.updateValueAndValidity();
  }
}

以及注册组件表单:

this.mySignupForm = new FormGroup({
          captcha: new FormControl()
        });

任何人都可以看到我做错了什么吗?

最佳答案

错误没有名称为“captcha”的表单控件的值访问器。可以通过使用 forwardRef 将指令/控件添加到所有可用 NG_VALUE_ACCESSOR 的列表来解决此问题。您正在有效地扩展 NG_VALUE_ACCESSOR 的多提供程序,以便该指令可以访问 ControlValueAccessor

@Directive({
  selector: '[nbRecaptcha]',
  providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: forwardRef(() => RecaptchaDirective),
      multi: true
    },
    ReCaptchaAsyncValidator
  ]
})

这是一个主要工作的 example该特定错误已得到解决。我必须删除示例中的一些自定义类/配置,因为我不知道它们的确切实现。

我找不到官方documentation用于创建自定义控件,但是有一些可靠的文章讨论创建引用此必要注册的自定义控件。

希望有帮助!

关于javascript - Angular:尝试添加验证码。错误 => 没有名称为 'captcha' 的表单控件的值访问器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52958954/

相关文章:

javascript - 使用 Jquery 在另一个元素第一次出现之前插入元素/文本

angular - 子组件中的 formControlName

c# - 如何将刷新按钮添加到 mscaptcha 组件?

firefox - reCAPTCHA 在 Firefox 中不可见 - 运行 AdBlock 和 Ghostery。

javascript - Parsley js远程设置状态

javascript - 创建粘性导航 css 和 jquery

javascript - XSS - 使用 PHP 执行 Javascript

Angular 2 Http 请求不发送凭据

angular - chrome (macOs) 不显示桌面推送通知

javascript - 我如何修复包含 addthis 的验证码中的错误