5

I noticed that my new ReCaptcha only showed up "sometimes" so I tried to track it down.

I have a SPA using Angular and when loading on the "/contact" page, the ReCaptcha shows up. If I load into any other page and try to navigate to the "/contact" page the ReCaptcha is not there, but if I refresh on that page, it appears again. Navigating away and returning to this page will cause it to disappear again.

My setup is similar to the following:

index.html

<html ng-app="App">
<head>
  <meta charset="UTF-8">
  <base href="/">

  <title>...</title>

  <!-- STYLES -->
  <link rel="stylesheet" type="text/css" href="libs/bootstrap/dist/css/bootstrap.min.css" />
  <link rel="stylesheet" type="text/css" href="libs/font-awesome/css/font-awesome.min.css" />
  <link rel="stylesheet" type="text/css" href="dist/css/style.min.css" />
</head>
<body>

    <!-- HEADER AND NAVBAR -->
    <header>
        <nav class="navbar navbar-default">
        ...
        </nav>
    </header>

    <!-- MAIN CONTENT AND INJECTED VIEWS -->
    <div id="main" ng-controller="MainController">
        <!-- this is where content will be injected -->
        <div ng-view></div>
    </div>

    <!-- FOOTER -->
    <footer id="footer" ng-controller="FooterController">
        <div class="text-center">
            {{ footer }}
        </div>
    </footer>

    <!-- SCRIPTS -->
    <script src="libs/angular/angular.min.js"></script>
    <script src="libs/angular-resource/angular-resource.min.js"></script>
    <script src="libs/angular-route/angular-route.min.js"></script>
    <!-- ReCaptcha -->
    <script src='https://www.google.com/recaptcha/api.js'></script>

    <!-- APP -->
    <script src="dist/js/app.min.js"></script>
</body>

</html>

contact.html

<div class="jumbotron">
    <h1 class="text-center">Contact Page</h1>

    <p class="text-center">{{ message }}</p>
    <div data-ng-controller="ContactController" id="contact-form">
        <div>
            <div ng-show="sent" class="alert alert-success">
                <strong><span class="fa fa-send"></span> Success! Message sent.</strong>
            </div>    
            <div ng-show="error" class="alert alert-danger">
                <strong><span class="fa fa-exclamation-circle"></span> Error! Please check the inputs.</strong>
            </div>
        </div>
        <form name="contactForm" role="form" method="post">
            <div class="well well-sm">
                <span class="fa fa-asterisk"></span><strong> Required Field </strong>
            </div>
            <div class="form-group">
                <label for="InputName">Your Name</label>
                <div class="input-group">
                    <input type="text" class="form-control" name="InputName" id="InputName" placeholder="Enter Name" data-ng-model="Name" required>
                    <span class="input-group-addon"><i class="fa fa-asterisk"></i></span>
                </div>
            </div>
            <div class="form-group">
                <label for="InputEmail">Your Email</label>
                <div class="input-group">
                    <input type="email" class="form-control" id="InputEmail" name="InputEmail" placeholder="Enter Email" data-ng-model="Email" required>
                    <span class="input-group-addon"><i class="fa fa-asterisk"></i></span>
                </div>
            </div>
            <div class="form-group">
                <label for="InputSubject">Subject</label>
                <div class="input-group">
                    <select class="form-control" id="InputSubject" name="InputSubject" data-ng-model="Subject" ng-options="subject.type for subject in subjects"></select>
                </div>
            </div>
            <div class="form-group">
                <label for="InputMessage">Message</label>
                <div class="input-group">
                    <textarea name="InputMessage" id="InputMessage" class="form-control" rows="5" data-ng-model="Message" required></textarea>
                    <span class="input-group-addon"><i class="fa fa-asterisk"></i></span>
                </div>
            </div>
            <div class="g-recaptcha" data-sitekey="[my_site_key]"></div>
            <button name="submit" id="submit" class="btn btn-info pull-right" data-ng-click="submit(contactForm)">Submit</button>
        </form>
    </div>
</div>

These are the only two areas that seem to affect the ReCaptcha at this point. If I can provide anymore info, please let me know.

I've looked through the Google ReCaptcha API Docs and tried to implement some of their examples but nothing seemed to work. I've also looked around SO, as well as other sites to see if anyone else was having this issue, but my search has been fruitless so far. I'll keep looking.

2
  • Changing states removes and adds elements to DOM. When you go back to the same /contacts state, the div with recaptcha is loaded into DOM, but recaptcha js doesn't know that. Take a look at this implementation of Angular-recaptcha for ideas on how to fix (or use the library as is). I haven't used recaptcha or this library, so don't treat this suggestion as an endorsement.
    – New Dev
    Commented Dec 24, 2014 at 4:30
  • @NewDev A few similar questions also lead to this resource. The library itself is using an older version of recaptcha, but perhaps I'll fork it and offer a pull request using the new version. It seems like it shouldn't be that hard. Thanks for reaffirming my belief that this was probably the way to go and ultimately pushing me to try it.
    – McTalian
    Commented Dec 24, 2014 at 4:56

2 Answers 2

5

I ended up using vc-recaptcha to get this working.

Setup is pretty simple and it is updated fairly regularly.

1

This answer works for me with the new reCaptcha (I'm not a robot)

in Html (be sure to insert it within a form tag):

 <recaptcha></recaptcha>

Directive Code

angular.module('app').directive('recaptcha',['$window','$compile',function($window, $compile) {
  return {
    replace: true,
    link: function(scope, elem){
      var key = 'xxxxxxxxxxxxxxxxxxxxx';          <--<your public key
      activate();
      function activate(){
      if (angular.isDefined($window.grecaptcha)) {        
           $window.grecaptcha.render(elem[0],{
             'sitekey': key
             });           
        } else {
          activate();  **<- no good -> use some kind of promise here, just for testing**
        }
      }
    }          
  };
}]);

In old recpatche it is some kind of

  $window.grecaptcha.render(elem[0], key);   

Check API documentation for that.

Check here: http://www.codedodle.com/2014/12/google-new-recaptcha-using-javascript.html

1
  • Thank you so much for sharing this solution. One aspect of this solution worked for my angularjs single page web application as follows. By placing $window.grecaptcha.render() inside the controller associated with each view, you can coax respective grecaptcha widgets to load between different views. Much appreciated.
    – Ben Gross
    Commented Apr 7, 2021 at 20:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.