Skip to content

Commit

Permalink
Merged development into master
Browse files Browse the repository at this point in the history
  • Loading branch information
DethAriel committed Aug 31, 2016
2 parents 1b4d5e0 + 3d3dab5 commit 31f4b02
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 91 deletions.
174 changes: 89 additions & 85 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![Build Status](https://travis-ci.org/DethAriel/ng2-recaptcha.svg?branch=master)](https://travis-ci.org/DethAriel/ng2-recaptcha)
[![devDependency Status](https://david-dm.org/dethariel/ng2-recaptcha/dev-status.svg)](https://david-dm.org/dethariel/ng2-recaptcha?type=dev)

A simple, configurable, easy-to-start component for handling reCAPTCHA.
A simple, configurable, easy-to-start component for handling reCAPTCHA.

## Installation

Expand All @@ -15,28 +15,63 @@ The easiest way is to install trough [npm](https://www.npmjs.com/package/ng2-rec
npm i ng2-recaptcha --save
```

In order to take advantage of type-checking system you should also install `grecaptcha` typings:

```
typings install dt~grecaptcha --save --global
```

## <a name="example-basic"></a>Usage [(see in action)](https://dethariel.github.io/ng2-recaptcha/basic)

To start with, you need to add one of the `Recaptcha` modules (more on that [later](#modules)):

```typescript
import { RecaptchaModule } from 'ng2-recaptcha';
import { BrowserModule } from '@angular/platform-browser';

@NgModule({
bootstrap: [MyApp],
declarations: [MyApp],
imports: [
BrowserModule,
RecaptchaModule.forRoot(), // Keep in mind the "forRoot"-magic nuances!
],
})
export class MyAppModule { }
```

Once you have done that, the rest is simple:

```typescript
import { bootstrap } from '@angular/platform-browser-dynamic';
import { browserDynamicPlatform } from '@angular/platform-browser-dynamic';
import { Component } from '@angular/core';
import { RecaptchaComponent, RecaptchaLoaderService } from 'ng2-recaptcha/ng2-recaptcha';

@Component({
selector: 'my-app',
template: `
<recaptcha (resolved)="resolved($event)" siteKey="YOUR_SITE_KEY"></recaptcha>
`,
directives: [RecaptchaComponent],
template: `<recaptcha (resolved)="resolved($event)" siteKey="YOUR_SITE_KEY"></recaptcha>`,
}) export class MyApp {
resolved(captchaResponse: string) {
console.log(`Resolved captcha with response ${captchaResponse}:`);
}
}

bootstrap(MyApp, [RecaptchaLoaderService]);
browserDynamicPlatform().bootstrapModule(MyAppModule);
```

## <a name="modules"></a>Modules: "Forms"-ready and "No-forms"

There are two modules available for you:

```typescript
import { RecaptchaModule } from 'ng2-recaptcha';
import { RecaptchaNoFormsModule } from 'ng2-recaptcha/ng2-recaptcha.noforms';
```

The difference between them consists in dependencies - `RecaptchaModule` depends on
`@angular/forms`, while `RecaptchaNoFormsModule` does not. If you do not rely on
Angular 2 forms in your project, you should use the "no-forms" module version, as
it does not require the `@angular/forms` package to be bundled with your code.

## Options

The component supports this options:
Expand All @@ -52,7 +87,7 @@ so I won't duplicate it here.

## Events

* `resolved(response: string)`. Occurs when the captcha resolution value changed.
* `resolved(response: string)`. Occurs when the captcha resolution value changed.
When user resolves captcha, use `response` parameter to send to the server for verification.
This parameter is equivalent to calling [`grecaptcha.getResponse`](https://developers.google.com/recaptcha/docs/display#js_api).

Expand All @@ -67,25 +102,23 @@ validation failed, and you need the user to re-enter the captcha.
## <a name="example-language"></a>Specifying a different language [(see in action)](https://dethariel.github.io/ng2-recaptcha/language)

`<recaptcha>` supports various languages. But this settings is global, and cannot be set
on a per-captcha basis. An example below shows you how can the default behavior be overridden.
on a per-captcha basis. This can be overridden by providing your own instance of
`RecaptchaLoaderService` for a particular module:

```typescript
import { bootstrap } from '@angular/platform-browser-dynamic';
import { Component, provide } from '@angular/core';
import { RecaptchaLoaderService } from 'ng2-recaptcha/ng2-recaptcha';

@Component({
selector: 'my-app',
templateUrl: 'my-app.html',
}) export class MyApp {}

bootstrap(MyApp, [
provide(RecaptchaLoaderService, {
useValue: new RecaptchaLoaderService("fr"),
})
]);
import { RecaptchaLoaderService } from 'ng2-recaptcha';

@NgModule({
providers: [
{
provide: RecaptchaLoaderService,
useValue: new RecaptchaLoaderService("fr"), // use French language
},
],
}) export class MyModule { }
```

```
You can find the list of supported languages in [reCAPTCHA docs](https://developers.google.com/recaptcha/docs/language).

## <a name="example-preload-api"></a>Loading the reCAPTCHA API by yourself [(see in action)](https://dethariel.github.io/ng2-recaptcha/preload-api)

Expand All @@ -95,90 +128,61 @@ instance of this service to the Angular DI.

The below code snippet is an example of how such a provider can be implemented.

**TL;DR**: there should be an `Observable` that eventually resolves to a
**TL;DR**: there should be an `Observable` that eventually resolves to a
`grecaptcha`-compatible object (e.g. `grecaptcha` itself).

```html
<script src="https://www.google.com/recaptcha/api.js?render=explicit&amp;onload=onloadCallback"></script>

<script>
// bootstrap the application once the reCAPTCHA api has loaded
// bootstrap the application once the reCAPTCHA api has loaded
function onloadCallback() {
System.import('app').catch(function(err) { console.error(err); });
}
</script>
```

```typescript
import { bootstrap } from '@angular/platform-browser-dynamic';
import { Component, Injectable, provide } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
import { Observable } from 'rxjs/Observable';
import {
RecaptchaComponent,
RecaptchaLoaderService,
} from 'ng2-recaptcha/ng2-recaptcha';
import { RecaptchaLoaderService } from 'ng2-recaptcha';

@Injectable()
export class PreloadedRecaptchaAPIService {
public ready: Observable<ReCaptchaV2.ReCaptcha>;

constructor() {
constructor() {
let readySubject = new BehaviorSubject<ReCaptchaV2.ReCaptcha>(grecaptcha);
this.ready = readySubject.asObservable();
}
}

@Component({
selector: 'my-app',
template: 'my-app.html',
})
export class MyApp { }

bootstrap(MyApp, [
provide(RecaptchaLoaderService, {
useValue: new PreloadedRecaptchaAPIService(),
})
]);
```

**Note**, that in order to take advantage of type-checking system the above code snippet references
`ReCaptchaV2.ReCaptcha`. In order to be able to use that in your code, run the following command:

```bash
typings install dt~grecaptcha --save --global
@NgModule({
providers: [
{
provide: RecaptchaLoaderService,
useValue: new PreloadedRecaptchaAPIService(),
},
],
}) export class MyModule { }
```

## <a name="example-forms"></a>Usage with `required` in forms [(see in action)](https://dethariel.github.io/ng2-recaptcha/forms)

It's very easy to put `recaptcha` in an Angular2 form and have it `require`d.

* Import value accessor so that forms library known how to handle `recaptcha`:

```typescript
import { RecaptchaValueAccessor } from 'ng2-recaptcha/ng2-recaptcha.forms';
```
* Add a `RecaptchaValueAccessor` directive to the list of your form component directives:

```typescript
@Component({
selector: 'my-form',
template: `
<form #captchaProtectedForm="ngForm">
<recaptcha
[(ngModel)]="formModel.captcha"
name="captcha"
required
siteKey="YOUR_SITE_KEY"
#captcha="ngModel"
></recaptcha>
<div [hidden]="captcha.valid || captcha.pristine" class="error">Captcha must be solved</div>
</form>
`,
directives: [RecaptchaComponent, RecaptchaValueAccessor],
})
export class MyForm {
formModel = new MyFormModel();
}
```
* You're done!
It's very easy to put `recaptcha` in an Angular2 form and have it `require`d - just
add the `required` attribute to the `<recaptcha>` element

```typescript
@Component({
selector: 'my-form',
template: `
<form>
<recaptcha
[(ngModel)]="formModel.captcha"
name="captcha"
required
siteKey="YOUR_SITE_KEY"
></recaptcha>
</form>`,
}) export class MyForm {
formModel = new MyFormModel();
}
```
4 changes: 0 additions & 4 deletions ng2-recaptcha.forms.ts

This file was deleted.

3 changes: 3 additions & 0 deletions ng2-recaptcha.noforms.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './recaptcha/recaptcha.component';
export * from './recaptcha/recaptcha-loader.service';
export * from './recaptcha/recaptcha-noforms.module';
2 changes: 2 additions & 0 deletions ng2-recaptcha.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export * from './recaptcha/recaptcha.component';
export * from './recaptcha/recaptcha-loader.service';
export * from './recaptcha/recaptcha-value-accessor.directive';
export * from './recaptcha/recaptcha.module';
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ng2-recaptcha",
"version": "1.2.0",
"version": "1.3.0",
"description": "Angular 2 + TypeScript component for Google reCAPTCHA",
"scripts": {
"types": "typings install",
Expand Down
19 changes: 19 additions & 0 deletions recaptcha/recaptcha-noforms.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { ModuleWithProviders, NgModule } from '@angular/core';

import { RecaptchaLoaderService } from './recaptcha-loader.service';
import { RecaptchaComponent } from './recaptcha.component';

@NgModule({
declarations: [ RecaptchaComponent ],
exports: [ RecaptchaComponent ],
})
export class RecaptchaNoFormsModule {
public static forRoot(): ModuleWithProviders {
return {
ngModule: RecaptchaNoFormsModule,
providers: [
RecaptchaLoaderService,
],
};
}
}
23 changes: 23 additions & 0 deletions recaptcha/recaptcha.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ModuleWithProviders, NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';

import { RecaptchaLoaderService } from './recaptcha-loader.service';
import { RecaptchaValueAccessorDirective } from './recaptcha-value-accessor.directive';
import { RecaptchaComponent } from './recaptcha.component';

@NgModule({
declarations: [
RecaptchaValueAccessorDirective,
RecaptchaComponent,
],
exports: [RecaptchaComponent, RecaptchaValueAccessorDirective],
imports: [FormsModule],
})
export class RecaptchaModule {
public static forRoot(): ModuleWithProviders {
return {
ngModule: RecaptchaModule,
providers: [RecaptchaLoaderService],
};
}
}
2 changes: 1 addition & 1 deletion typings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"globalDependencies": {
"core-js": "registry:dt/core-js#0.0.0+20160602141332",
"core-js": "registry:dt/core-js#0.0.0+20160725163759",
"grecaptcha": "registry:dt/grecaptcha#0.0.0+20160808210619"
}
}

0 comments on commit 31f4b02

Please sign in to comment.