var app = angular.module('plunker', ['vcRecaptcha']);

app.controller('MainCtrl', function($scope) {
  $scope.userModel = {
    name: 'jackkum',
    email: 'jackkum@bk.ru'
  };
  
  $scope.submit = console.log;
});
<!DOCTYPE html>
<html ng-app="plunker">

  <head>
    <meta charset="utf-8" />
    <title>AngularJS Plunker</title>
    <script>document.write('<base href="' + document.location + '" />');</script>
    <link href="style.css" rel="stylesheet" />
    <script src="//www.google.com/recaptcha/api.js?onload=vcRecaptchaApiLoaded&amp;render=explicit" async defer></script>
    
    <script data-semver="1.3.17" src="https://code.angularjs.org/1.3.17/angular.js" data-require="angular.js@1.3.x"></script>
    <script src="angular-recaptcha.js"></script>
    <script src="app.js"></script>
  </head>

  <body ng-controller="MainCtrl">
    <p>Hello {{userModel.name}}!</p>
    
    <form class="form" name="form" ng-submit="submit(form)" novalidate>
      <div>
        <label>
          Name
          <input type="text" ng-model="userModel.name">
        </label>
      </div>
      
      <div>
        <label>
          Email
          <input type="email" ng-model="userModel.email">
        </label>
      </div>
      
      <div>
        <div vc-recaptcha key="'6LdoEggTAAAAABy3Km-rGbf8z7zob0DkASZ2xNsM'" ng-model="userModel.response"></div>
      </div>
      
      <div ng-show="form.$error.recaptcha" class="error-message">Are you a human?</div>
      
      <div>
        <button type="submit" ng-disabled="form.$invalid">Save</button>
      </div>
      
    </form>
    
    <pre>form = {{form | json}}</pre>
  </body>
</html>
/* Put your css in here */

.error-message {
  color: red;
}
/**
 * angular-recaptcha build:2015-06-22 
 * https://github.com/vividcortex/angular-recaptcha 
 * Copyright (c) 2015 VividCortex 
**/

/*global angular, Recaptcha */
(function (ng) {
    'use strict';

    ng.module('vcRecaptcha', []);

}(angular));

/*global angular */
(function (ng) {
    'use strict';

    var app = ng.module('vcRecaptcha');

    /**
     * An angular service to wrap the reCaptcha API
     */
    app.service('vcRecaptchaService', ['$window', '$q', function ($window, $q) {
        var deferred = $q.defer(), promise = deferred.promise, recaptcha;

        $window.vcRecaptchaApiLoaded = function () {
            recaptcha = $window.grecaptcha;

            deferred.resolve(recaptcha);
        };


        function getRecaptcha() {
            if (!!recaptcha) {
                return $q.when(recaptcha);
            }

            return promise;
        }

        function validateRecaptchaInstance() {
            if (!recaptcha) {
                throw new Error('reCaptcha has not been loaded yet.');
            }
        }


        // Check if grecaptcha is not defined already.
        if (ng.isDefined($window.grecaptcha)) {
            $window.vcRecaptchaApiLoaded();
        }

        return {

            /**
             * Creates a new reCaptcha object
             *
             * @param elm  the DOM element where to put the captcha
             * @param key  the recaptcha public key (refer to the README file if you don't know what this is)
             * @param fn   a callback function to call when the captcha is resolved
             * @param conf the captcha object configuration
             */
            create: function (elm, key, fn, conf) {
                conf.callback = fn;
                conf.sitekey = key;

                return getRecaptcha().then(function (recaptcha) {
                    return recaptcha.render(elm, conf);
                });
            },

            /**
             * Reloads the reCaptcha
             */
            reload: function (widgetId) {
                validateRecaptchaInstance();

                // $log.info('Reloading captcha');
                recaptcha.reset(widgetId);

                // reCaptcha will call the same callback provided to the
                // create function once this new captcha is resolved.
            },

            /**
             * Gets the response from the reCaptcha widget.
             *
             * @see https://developers.google.com/recaptcha/docs/display#js_api
             *
             * @returns {String}
             */
            getResponse: function (widgetId) {
                validateRecaptchaInstance();

                return recaptcha.getResponse(widgetId);
            }
        };

    }]);

}(angular));

/*global angular, Recaptcha */
(function (ng) {
    'use strict';

    function throwNoKeyException() {
        throw new Error('You need to set the "key" attribute to your public reCaptcha key. If you don\'t have a key, please get one from https://www.google.com/recaptcha/admin/create');
    }

    var app = ng.module('vcRecaptcha');

    app.directive('vcRecaptcha', ['$document', '$timeout', 'vcRecaptchaService', function ($document, $timeout, vcRecaptcha) {

        return {
            restrict: 'A',
            require: "?^^form",
            scope: {
                response: '=?ngModel',
                key: '=',
                theme: '=?',
                size: '=?',
                tabindex: '=?',
                onCreate: '&',
                onSuccess: '&',
                onExpire: '&'
            },
            link: function (scope, elm, attrs, ctrl) {
                if (!attrs.hasOwnProperty('key')) {
                    throwNoKeyException();
                }

                scope.widgetId = null;

                var removeCreationListener = scope.$watch('key', function (key) {
                    if (!key) {
                        return;
                    }

                    if (key.length !== 40) {
                        throwNoKeyException();
                    }

                    var callback = function (gRecaptchaResponse) {
                        // Safe $apply
                        $timeout(function () {
                            if(ctrl){
                                ctrl.$setValidity('recaptcha',true);
                            }
                            scope.response = gRecaptchaResponse;
                            // Notify about the response availability
                            scope.onSuccess({response: gRecaptchaResponse, widgetId: scope.widgetId});
                        });

                        // captcha session lasts 2 mins after set.
                        $timeout(function (){
                            if(ctrl){
                                ctrl.$setValidity('recaptcha',false);
                            }
                            scope.response = "";
                            // Notify about the response availability
                            scope.onExpire({widgetId: scope.widgetId});
                        }, 2 * 60 * 1000);
                    };

                    vcRecaptcha.create(elm[0], key, callback, {

                        theme: scope.theme || attrs.theme || null,
                        tabindex: scope.tabindex || attrs.tabindex || null,
                        size: scope.size || attrs.size || null

                    }).then(function (widgetId) {
                        // The widget has been created
                        if(ctrl){
                            ctrl.$setValidity('recaptcha',false);
                        }
                        scope.widgetId = widgetId;
                        scope.onCreate({widgetId: widgetId});

                        scope.$on('$destroy', cleanup);

                    });

                    // Remove this listener to avoid creating the widget more than once.
                    removeCreationListener();
                });

                function cleanup(){
                  // removes elements reCaptcha added.
                  angular.element($document[0].querySelectorAll('.pls-container')).parent().remove();
                }
            }
        };
    }]);

}(angular));