The click of the directive is called twice

advertisements

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.


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.