Click here to Skip to main content
15,880,427 members
Articles / Programming Languages / Javascript

Using reCAPTCHA in Single-page Applications

Rate me:
Please Sign up or sign in to vote.
5.00/5 (1 vote)
8 Aug 2015CPOL2 min read 9.3K   2  
Using reCAPTCHA in Single-page applications

Recently, I was writing my first Single-page application using Angular.js. The application should allow posting content as an anonymous user, so some sort of verification needs to be in place to make sure it’s actually a human user. For years, reCAPTCHA has been probably the most popular way to achieve that, so I went and used AngularJS reCaptcha component in my app. The examples of usage are quite simple:

XML
<div vc-recaptcha theme="light" key="[my public key]"></div>

In my controller, I called getResponse method to get the response value returned by reCAPTCHA, which is then sent to the server and validated there:

JavaScript
var response = vcRecaptchaService.getResponse();

I got it working within 15 minutes or so. It was great until I started noticing a strange error in my browser. After successful verification by reCAPTCHA, when submitting my form, I got an error (I took the message from Chrome console):

TypeError: Cannot read property 'value' of null
    at Object.In [as getResponse] (https://www.gstatic.com/recaptcha/api2/r20150804120649/recaptcha__en.js:312:279)
    at Object.getResponse (http://localhost:61907/Scripts/angular-recaptcha.js:96:34)
    at n.$scope.submit (http://localhost:61907/App/controllers/viewController.js:85:49)
    at fn (eval at  (http://localhost:61907/Scripts/angular.min.js:1:0), :4:209)
    at f (http://localhost:61907/Scripts/angular.min.js:252:74)
    at n.$eval (http://localhost:61907/Scripts/angular.min.js:134:493)
    at n.$apply (http://localhost:61907/Scripts/angular.min.js:135:217)
    at HTMLButtonElement. (http://localhost:61907/Scripts/angular.min.js:252:126)
    at HTMLButtonElement.Hf.c (http://localhost:61907/Scripts/angular.min.js:35:217)

Not quite sure what’s happening, I kept ignoring this bug until other features were complete. Then, I had to come back and fix this.

The reCAPTCHA JS file was minified, so it didn’t mean much when I took a look at the original source of the error. Furthermore, it all seemed to work when I tried to reproduce it. After some manual monkey testing to reproduce the bug, I took a look at the DOM structure generated by reCAPTCHA component. Bingo! the ID of the element where the response value from reCAPTCHA service is stored was changed: instead of standard “g-recaptcha-response”, it always was “g-recaptcha-response-1″ when the error occurred. So the “Cannot read property ‘value’ of null” message in this case indicated that the component cannot find an element by ID…

That’s when it started to make sense to me. In my application, I had two forms with reCAPTCHA and they were in different views. Since Single-page applications do not reload the page, when rendering the second view, reCAPTCHA response element was automatically assigned a new unique ID by simply adding an incremented number to “g-recaptcha-response”.

Fixing the error was pretty straightforward then. getResponse method from reCAPTCHA accepts a widgetId parameter, which is the ID of reCAPTCHA response element. The fix in my code looks like the following:

XML
<div vc-recaptcha theme="light" 
key="[my public key]" on-create="setRecaptchaId(widgetId)"></div>
JavaScript
$scope.setRecaptchaId = function(widgetId) {
    $scope.recaptchaId = widgetId;
};
...
var response = vcRecaptchaService.getResponse($scope.recaptchaId);

This code just executes a callback function to get and save the currently rendered reCAPTCHA response element ID. When the response is needed, this ID is then passed to getResponse method.

The exact source code may look different depending on the components that you use, but the general idea is the same: if you render reCAPTCHA more than once, you must pass a widgetId parameter when calling getResponse method.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
Lithuania Lithuania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --