0

我正在尝试使用 prettyCheckbox 插件将样式应用于我的复选框。对于那些不知道插件的工作方式的人,它隐藏了原始复选框并显示另一个样式对象。我创建了一个指令,它为每个复选框实例化插件。

点击假复选框的插件设置真实输入元素的属性并调用更改 - 但是这似乎并没有更新模型:

input.prop('checked', true).change();

我稍微修改了 prettyCheckbox 插件,因此使用单击事件更改了原始复选框以更新模型:

input.trigger('click');

这很好用,但是复选框似乎总是具有您期望它具有的完全相反的值:如果未选中复选框,则为 true;如果选中了复选框,则为 false。我似乎无法弄清楚为什么会这样。我创建了一个 plunkr 来向您展示正在发生的事情:

http://plnkr.co/edit/YVq2is0khGgLRWbHk2aB?p=preview

在此先感谢您的帮助:)

4

2 回答 2

1

input.trigger('click')在另一个事件处理程序的中间调用。因为 JavaScript 是单线程的,事件循环一次只能处理一个事件,而一个事件已经在处理,所以一旦事件队列空闲,这个事件就会被处理。在您的情况下,当您的“点击”事件可以被处理时,它是在 Angular 完成运行摘要循环之后。这意味着 Angular 在您的复选框被实际单击之前已经完成了处理,当复选框单击完成时,Angular 会忽略它,因为它认为“showRedBox”值是干净的(不脏的)。直到您再次单击漂亮的复选框,angular 才会再次查看“showRedBox”,将其当前值与旧值进行比较,识别出它是脏的,并更新 DOM。当然,到完成时,您的复选框尚未再次更改状态,因此它不同步。打电话$scope.$apply()或者$scope.$digest()在这种情况下无济于事,因为 Angular 已经认为“showRedBox”是干净的。您必须首先修改 angular 的数据,以便它将“showRedBox”值识别为脏值,只有在您可以访问范围(您没有)时才能这样做。

解决方法:直接使用scope.showRedBox = fakeCheckable.hasClass("checked");而不是input.trigger('click')修改“showRedBox”值。此解决方案将要求您将插件的范围固定在指令的封闭范围内。

于 2013-08-02T16:50:04.163 回答
1

对,所以我发现了这个 jsfiddle,它确实帮助我在不使用漂亮的复选框插件的情况下解决问题:

http://jsfiddle.net/evaneus/z9rge/

正如詹姆斯在他的回答中提到的那样,指令需要访问控制器:

angular.module('buttonToggle', []).directive('buttonToggle', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function($scope, element, attr, ctrl) {
            var classToToggle = attr.buttonToggle;
            element.bind('click', function() {
                var checked = ctrl.$viewValue;
                $scope.$apply(function(scope) {
                    ctrl.$setViewValue(!checked);
                });
            });

            $scope.$watch(attr.ngModel, function(newValue, oldValue) {
                newValue ? element.addClass(classToToggle) : element.removeClass(classToToggle);
            });
        }
    };
});


<p>
  <input id="gradeCheck" type="checkbox" ng-model="myModel['A']"> A
  <input type="checkbox" ng-model="myModel['B']"> B
  <input type="checkbox" ng-model="myModel['C']"> C
  <input type="checkbox" ng-model="myModel['D']"> D
</p> 

<p>
  <button button-toggle="active" class="btn" ng-model="myModel['A']">A</button>
  <button button-toggle="active" class="btn" ng-model="myModel['B']">B</button>
  <button button-toggle="active" class="btn" ng-model="myModel['C']">C</button>
  <button button-toggle="active" class="btn" ng-model="myModel['D']">D</button>
</p>

然后我只需要按照我想要的方式设置按钮的样式,无论是否有活动样式,并且所有工作都很好:)

于 2013-08-05T11:36:00.443 回答