Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Bootstrap 3 javascript checkbox and radio button toggle prevents angular's ng-model from updating on input #4516

Closed
@pholly

Description

@pholly

When using Bootstrap 3's javascript buttons for checkboxes, the checkbox's ng-model does not get updated. Looking into the source code for both I know why.

Bootstrap 3 html for checkbox button group:

<div class="btn-group" data-toggle="buttons">
  <label class="btn btn-primary">
    <input type="checkbox"> Option 1
  </label>
  <label class="btn btn-primary">
    <input type="checkbox"> Option 2
  </label>
  <label class="btn btn-primary">
    <input type="checkbox"> Option 3
  </label>
</div>

Bootstrap 3 javascript for button toggle:

Button.prototype.toggle = function () {
        var $parent = this.$element.closest('[data-toggle="buttons"]')

        if ($parent.length) {
            var $input = this.$element.find('input')
              .prop('checked', !this.$element.hasClass('active'))
              .trigger('change')
            if ($input.prop('type') === 'radio') $parent.find('.active').removeClass('active')
        }

        this.$element.toggleClass('active')
    }

Angular source for checkbox (radio button is similar):

function checkboxInputType(scope, element, attr, ctrl) {
        var trueValue = attr.ngTrueValue,
            falseValue = attr.ngFalseValue;

        if (!isString(trueValue)) trueValue = true;
        if (!isString(falseValue)) falseValue = false;

        element.on('click', function () {
            scope.$apply(function () {
                ctrl.$setViewValue(element[0].checked);
            });
        });

        ctrl.$render = function () {
            element[0].checked = ctrl.$viewValue;
        };

        ctrl.$formatters.push(function (value) {
            return value === trueValue;
        });

        ctrl.$parsers.push(function (value) {
            return value ? trueValue : falseValue;
        });
    }

The problem is Angular's checkbox is listening for the click event whereas Bootstrap's button handles the click event and fires the change event on the checkbox input.

I wrote a simple directive that does exactly what Angular's checkbox click event listener does but instead listens for the change event.

appModule.directive('mccCheckboxDetectChange', [function mccCheckboxDetectChange() {

    return {
        replace: false,
        require: 'ngModel',
        scope: false,
        link: function (scope, element, attrs, ngModelCtrl) {
            element.on('change', function () {
                scope.$apply(function () {
                    ngModelCtrl.$setViewValue(element[0].checked);
                });
            });
        }
    };
}]);

Is there a reason why Angular listens for the click event for radio and checkboxes instead of the change event? Should I create a pull request and change the click event listener to be a change event listener? This would be my first pull request.

Thanks!
Philip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions