简体   繁体   中英

How to reload simple captcha in directive?

I am using a simple captcha on my pop-up dialog using bPopup plugin.

You can refer the captcha code to this jsfiddle: https://jsfiddle.net/Mazzu/hspxaeqa/

HTML:

<span id="popup-button-email">Click Here!</span>

<div id="popup-second"> <a class="b-close">x<a/>
        <simple-captcha valid="captchaValid"></simple-captcha>
</div>

JS:

app.directive('simpleCaptcha', function() {
    return {
        restrict: 'E',
        scope: { valid: '=' },
        template: '<input ng-model="a.value" ng-show="a.input" style="width:2em; text-align: center;"><span ng-hide="a.input">{{a.value}}</span>&nbsp;{{operation}}&nbsp;<input ng-model="b.value" ng-show="b.input" style="width:2em; text-align: center;"><span ng-hide="b.input">{{b.value}}</span>&nbsp;=&nbsp;{{result}}',
        controller: function($scope) {

            var show = Math.random() > 0.5;

            var value = function(max){
                return Math.floor(max * Math.random());
            };

            var int = function(str){
                return parseInt(str, 10);
            };

            $scope.a = {
                value: show? undefined : 1 + value(4),
                input: show
            };
            $scope.b = {
                value: !show? undefined : 1 + value(4),
                input: !show
            };
            $scope.operation = '+';

            $scope.result = 5 + value(5);

            var a = $scope.a;
            var b = $scope.b;
            var result = $scope.result;

            var checkValidity = function(){
                if (a.value && b.value) {
                    var calc = int(a.value) + int(b.value);
                    $scope.valid = calc == result;
                } else {
                    $scope.valid = false;
                }
                $scope.$apply(); // needed to solve 2 cycle delay problem;
            };


            $scope.$watch('a.value', function(){    
                checkValidity();
            });

            $scope.$watch('b.value', function(){    
                checkValidity();
            });
        }
    };
});

POPUP:

$('#popup-button-email').bind('click', function(e) {
    // Prevents the default action to be triggered. 
    e.preventDefault();

    // Triggering bPopup when click event is fired
    $('#popup-second').bPopup();
});

All looks fine, except one thing.

After I close the pop-up, and I open another pop-up, it didn't reload the captcha, which is very odd.

Any ideas how to reload the captcha after I close the pop-up?

Thanks

You need to update just one or two things. In checkvalidity function of directive $scope.$apply() causing $digest cycle to run when it's already in progress, so breaking it, to avoid that you can have checkvalidity function in scope variable of directive's controller & remove this explicit calling of $apply. Also, as $('#popup-second').bPopup() calling does not actually re-render the directive so it always showing first time loaded results of directive. So what you can do is have ng-if on that directive element in your view & toggle it on onClose & onOpen events of bPopup(). So your template can be:

<div id="popup-second" style="display: none">
    <div> From Controller : {{mymodel.captchaValid}}
    </div>
    <div ng-if="show">
      <simple-captcha valid="mymodel.captchaValid"></simple-captcha>
    </div>
</div>

Update checkvalidity function inside directive as:

$scope.checkValidity = function() {
    if (a.value && b.value) {
      var calc = int(a.value) + int(b.value);
      $scope.valid = calc == result;
    } else {
      $scope.valid = false;
    }
};

$scope.$watch('a.value', function(){    
    $scope.checkValidity();
});

$scope.$watch('b.value', function(){    
    $scope.checkValidity();
});

And in controller of view call bPopup as:

$('#popup-button-email').bind('click', function(e) {
    // Prevents the default action to be triggered.
    e.preventDefault();

    // Triggering bPopup when click event is fired
    $('#popup-second').bPopup({
      onOpen: function() {
        $scope.show = true;
        $scope.$digest();
      },
      onClose: function() {
        $scope.show = false;
        $scope.$digest();
      }
    });
});

So in this way the directive is re-created every time you trigger it. So it'll give expected results & thanks to isolated scope you can reuse it multiple times on same view or different view of the app.

Working plunker

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM