From c19489d2668f89c0277a5985920d3db299a78703 Mon Sep 17 00:00:00 2001 From: Ruslan Arkhipau Date: Mon, 13 Mar 2017 13:43:47 -0700 Subject: [PATCH] feat(component): add support for invisible reCAPTCHA fixes #18 --- README.md | 42 ++++++++++++++++++++++++++++++++ recaptcha/recaptcha.component.ts | 20 +++++++++++++-- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index a012372..331e2bb 100644 --- a/README.md +++ b/README.md @@ -187,3 +187,45 @@ add the `required` attribute to the `` element formModel = new MyFormModel(); } ``` + +## Working with invisible reCAPTCHA [(see in action)](https://dethariel.github.io/ng2-recaptcha/invisible) + +Working with [invisible reCAPTCHA](https://developers.google.com/recaptcha/docs/invisible) is almost the same as with regular one. +First, you need to provide the right size: + +```html + +``` + +You will also need to invoke the [`"execute()"`](https://developers.google.com/recaptcha/docs/invisible#programmatic_execute) method manually. This can be done by either obtaining a reference to `RecaptchaComponent` via `@ViewChild()`, or by using inline template reference: + +```html + +... + +``` + +Normally you would only submit a form when recaptcha response has been received. This can be achieved by reacting to `(resolved)` event and invoking submit logic when the captcha response is truthy (this will not try to submit the form when recaptcha response has expired). A sample implementation would look like this: + +```typescript +@Component({ + selector: 'my-form', + template: ` +
+ + +
`, +}) export class MyForm { + public submit(captchaResponse: string): void { + this.http.post({ + captcha: captchaResponse, + /* ... */ + }); + } +} +``` diff --git a/recaptcha/recaptcha.component.ts b/recaptcha/recaptcha.component.ts index d55fd93..140a7a5 100644 --- a/recaptcha/recaptcha.component.ts +++ b/recaptcha/recaptcha.component.ts @@ -27,7 +27,7 @@ export class RecaptchaComponent implements AfterViewInit, OnDestroy { @Input() public siteKey: string; @Input() public theme: ReCaptchaV2.Theme; @Input() public type: ReCaptchaV2.Type; - @Input() public size: ReCaptchaV2.Size; + @Input() public size: ReCaptchaV2.Size | 'invisible'; @Input() public tabIndex: number; @Output() public resolved = new EventEmitter(); @@ -63,6 +63,21 @@ export class RecaptchaComponent implements AfterViewInit, OnDestroy { this.subscription.unsubscribe(); } + /** + * Executes the invisible recaptcha. + * Does nothing if component's size is not set to "invisible". + */ + public execute(): void { + if (this.size !== 'invisible') { + return; + } + + if (this.widget != null) { + // tslint:disable-next-line:no-any + (this.grecaptcha as any).execute(this.widget); + } + } + public reset() { if (this.widget != null) { if (this.grecaptcha.getResponse(this.widget)) { @@ -96,7 +111,8 @@ export class RecaptchaComponent implements AfterViewInit, OnDestroy { this.zone.run(() => this.expired()); }, sitekey: this.siteKey, - size: this.size, + // tslint:disable-next-line:no-any + size: this.size as any, tabindex: this.tabIndex, theme: this.theme, type: this.type,