1

I wrote a custom directive to implement a button toggle. When I interact with the button and confirm that I want to toggle it, I get Uncaught Reference Error: on is not defined. I thought that I defined on as an HTML attribute in the custom <button-toggle></button-toggle> element. The reason for my concern is because I may want to send the value of on or off to the server. Where am I going wrong?

buttonToggle.html

<div class="btn-group btn-toggle">
    <button class="btn btn-sm" ng-class="{'btn-success':on, 'btn-default':!on}">ON</button>
    <button class="btn btn-sm" ng-class="{'btn-danger':off, 'btn-default':!off}">OFF</button>
</div>

buttonToggle.js

angular
    .module('myApp')
    .directive('buttonToggle', buttonToggle);

function buttonToggle() {

    function link(scope, elm, attr, ctrl){

        angular.element(elm).on('click', function(){

            var confirmResponse = (window.confirm("Are you sure?") === true);

            if( confirmResponse ) {
                  scope.on = !scope.on;
                  scope.off = !scope.off;
                 scope.$digest();
                if(on)
                    return off;
                else if(off)
                    return on;
            }

             scope.$digest();
        });
    }

    var directive = {
        restrict: 'AE',
        link: link,
        replace: true,
        templateUrl: 'buttonToggle.html',
        scope: {
            on: "=",
            off: "="
        }
    };

    return directive;
}

buttonToggleCtrl.js

angular.module('myApp').controller('buttonToggleCtrl', buttonToggleCtrl);

function buttonToggleCtrl($scope) {
  $scope.activeOn = true;
  $scope.activeOff = false;
}

index.html snippet

<button-toggle on="activeOn" off="activeOff"></button-toggle>

As a note, don't worry about how the button looks right now. I know it's messed up in the plnkr, but it looks fine in my app since I'm using Bootstrap there and not in the plnkr. Pay attention to the error being throw in the JavaScript console.

3
  • no need to wrap elm in angular.element() ... it's already done when passed to link. Can just do elm.on('click'.. Commented Sep 22, 2015 at 13:51
  • also doesn't make sense toggling 2 boolean variables when only one is needed Commented Sep 22, 2015 at 13:57
  • @charlietfl Both of those make sense, I'll be sure to change them. Commented Sep 22, 2015 at 14:05

1 Answer 1

1

If you passed your directive code through any static checker like JSHint, you would notice the culprits:

if(on)
    return off;
else if(off)
    return on;

You should use scope.on and scope.off in these four lines instead.

Sign up to request clarification or add additional context in comments.

1 Comment

Ahh, worked nicely. I need to setup JSHint in my grunt build. Thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.