Help putting Google's ReCaptcha 2.0 in a component


#1

google-recaptcha.js


import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['g-recaptcha'],
    attributeBindings: ['data-sitekey'],
    'data-sitekey': '6LcggAqwgTAAA234AAO5J44Z422341rdG1d4qQ234sasfasqDD-iYmVT5p5gv',
  didInsertElement: function() {
    var self = this;
    grecaptcha.render(self.$().prop('departments'), {
      'sitekey': self.get('data-sitekey')
    });
  }

});

google-recaptcha.hbs


<div id="departments"></div>
  {{yield}}

Then I just placed it in the form to give me an HTML structure like this:

<div data-sitekey="6LcggAqwgTAAA234AAO5J44Z422341rdG1d4qQ234sasfasqDD-iYmVT5p5gv" class="ember-view g-recaptcha" id="ember705"><div id="departments"></div>
  <!---->

</div>

Unfortunately, this renders absolutely nothing. Instead of dynamically loading the script I installed the bower dependency I found named recaptcha-ajax. Through some quick googlefu I have found two related questions found here and here, but still could not get it to work.

Since this is a common use case I am sure many people here have implemented Google’s Click ReCaptcha into their Ember projects. Can anyone point me in the right direction or inform me on how to debug this?

Any help whatsoever is greatly appreciated and will be compensated with good karma. Thank you in advance for your help.


#2

I am really new to ember, and I am taking a guess. Is it a problem with the shadow DOM like this issue in polymer: https://github.com/GoogleWebComponents/google-recaptcha/issues/4


#3

The element selector is incorrect in the render part.

You should use grecaptcha.render('departments', {...}) OR grecaptcha.render(self.$('#departments')[0], {...})


#4

@indream Surprisingly both of those, and the code I posted give me the same result which is:

Thanks for replying and trying to help me rectify the problem.


#5

I put together a quick POC that eschews the recaptcha-ajax bower component in favor for the Google API:

https://gist.github.com/thermokarst/ddd24e07d42202e344eb

app/components/google-recaptcha.js

import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['g-recaptcha'],

  attributeBindings: ['siteKey:data-sitekey'],

  siteKey: '6LcggAqwgTAAA234AAO5J44Z422341rdG1d4qQ234sasfasqDD-iYmVT5p5gv',
});

app/index.html

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Recaptcha</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    {{content-for 'head'}}

    <link rel="stylesheet" href="assets/vendor.css">
    <link rel="stylesheet" href="assets/recaptcha.css">

    {{content-for 'head-footer'}}
  </head>
  <body>
    {{content-for 'body'}}

    <script src="assets/vendor.js"></script>
    <script src="https://www.google.com/recaptcha/api.js" async defer></script>
    <script src="assets/recaptcha.js"></script>

    {{content-for 'body-footer'}}
  </body>
</html>

app/templates/applications.hbs

<h2 id="title">Welcome to Ember.js</h2>

{{google-recaptcha}}

config/environment.js (add to ENV for sake of example, that way we can GET from google)

contentSecurityPolicy: {
  'default-src': "'none'",
  'script-src': "'self' https://www.gstatic.com https://www.google.com",
  'font-src': "'self'",
  'connect-src': "'self'",
  'img-src': "'self'",
  'style-src': "'self'",
  'media-src': "'self'"
},

You probably don’t want to load the Google Recaptcha API file like this, but for the proof of concept it’ll do. Also, you probably need to take a closer look at the contentSecurityPolicy stuff for a production environment.

The didInsertElement is unnecessary because we can use attributeBindings to achieve the same end result.

This renders a div that looks like the following:

<div id="ember371" class="ember-view g-recaptcha" data-sitekey="6LcggAqwgTAAA234AAO5J44Z422341rdG1d4qQ234sasfasqDD-iYmVT5p5gv">
    <!-- GOOGLE-INSERTED JAZZ -->
</div

The rendered component looks like this: http://i.imgur.com/09As7Mh.png (can’t attach the image directly because I am a new user on the forum). I am using the same sitekey as the one you provided, which is why there is a site key error.

Hope that helps.


#6

I think you could also post the console log for us to find out the real cause.


#7

Is there any way to get the data-callback working with this in order to get the token?


#8

I resorted to loading the script async with getScript and then waiting for the object to become available:

Gist


#9

Thanks @thermokarst! This was quite helpful. Bryan