sirrocco
sirrocco

Reputation: 8055

Directive click getting called twice

I have the following directive:

mod.directive('mdCheckbox', function(){
        var link = function(scope, element, attr, ngModel){
        var inp = element.find('input');

        scope.$watch(function(){
            return ngModel.$viewValue;
        }, function(newVal){
            console.log('newVal: ' + newVal);
            if(newVal){
                inp.attr('checked', 'checked');
            }else{
                inp.removeAttr('checked');
            }
        });

        scope.clickT = function(evt){
            // ** why the need for stopPropagation ?
            evt.stopPropagation();
            console.log('click called');
            if(inp.is(':checked')){ 
                ngModel.$setViewValue(false);
                console.log('set to false');
            }else{
                ngModel.$setViewValue(true);
                console.log('set to true');
            }
        };
    };

    var directive = {
        restrict: 'EA',
        require: 'ngModel',
        scope: {
            text: '@mdText'
        },
        template: '<div ng-click="clickT($event)" class="checkbox"><input type="checkbox"/>' +
                    '<span>{{text}}</span></div>',
        replace: true,
        link: link
    };

    return directive;

});

and the html :

<md-checkbox md-text="Is Awesome" ng-model="user.isAwesome"></md-checkbox>

Now the clickT handler is called twice, and I have to stop propagation on it. But it's not clear to me why that happens. And the second problem is that even though this seems like it works, after a couple of clicks it stops working - the value doesn't change true/false anymore.

Here's a plunkr for testing

Thanks.

Upvotes: 2

Views: 836

Answers (3)

Igor Pantović
Igor Pantović

Reputation: 9246

You shouldn't change the DOM manually because you can use data binding for that. But I won't go into that since it isn't the answer to question you asked.

Problem in your example is code that toggles Checking/Unchecking checkbox. It's not an attribute, it's a property(it can be true/false, not contain a value).

The checked attribute doesn't update the checked property after initial load. The attribute is in fact related to defaultChecked property.

Change it to:

if (newVal) {
    inp.prop('checked', true);
} else {
    inp.prop('checked', false);
}

Working Plnkr

Also, you can remove stopPropagation call.

Upvotes: 4

Andr&#233; Werlang
Andr&#233; Werlang

Reputation: 5944

It works if you query ngModel instead of input.

if (ngModel.$viewValue) ...

Although I'm not sure what this directive buys you...

Upvotes: 0

tpie
tpie

Reputation: 6221

There was something weird about the way you were adding and removing the checked attribute. Keep it simple and just set the input to true or false.

Working Demo

scope.clickT = function(){

                console.log('click called');
                if(inp){ 
                    ngModel.$setViewValue(false);
                    console.log('set to false');
                }else{
                    ngModel.$setViewValue(true);
                    console.log('set to true');
                }
            };

Upvotes: 0

Related Questions