如何防止jQuery-UI按钮组破坏AngularJS绑定?

时间:2012-08-13 13:59:46

标签: javascript jquery-ui angularjs

在下面的代码中,我呼叫$(".test").buttonset();的事实正在打破{{ item.value() }}的更新。我认为它与jQuery UI重写DOM有关。

<html ng-app>
    <head>
        <link href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.7.2/themes/start/jquery-ui.css" type="text/css" rel="Stylesheet" />
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.8.21/jquery-ui.min.js"></script>
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
        <script type="text/javascript">
            function ExampleCtrl($scope, $timeout) {
                $scope.list = [
                    { name: "a", value: 5 },
                    { name: "b", value: 6 },
                    { name: "c", value: 5 },
                    { name: "d", value: 6 }
                ];

                $scope.calc = [
                    [
                        {
                            name: "a, b avg",
                            value: function() { return(($scope.list[0].value + $scope.list[1].value) / 2) }
                        },
                        {
                            name: "c, d avg",
                            value: function() { return(($scope.list[2].value + $scope.list[3].value) / 2) }
                        }
                    ]
                ];

                $timeout(function() {
                    $(".test").buttonset();
                }, 0);
            }
        </script>
    </head>
    <body ng-controller="ExampleCtrl">
        <div class="test" ng-repeat="group in calc">
            <div ng-repeat="item in group">
                <input type="radio" name="a" id="{{item.name}}" />
                <label for="{{item.name}}">{{item.name}}: {{ item.value() }}</label>
            </div>
        </div>

        <ul ng-repeat="item in list">
            <li>{{item.name}}: <input type="number" ng-model="item.value" />
        </ul>
    </body>
</html>

这是一个jsFiddle版本:http://jsfiddle.net/vhLXW/

2 个答案:

答案 0 :(得分:2)

控制器中的Dom操作并不是一个好主意。您可以做的是创建一个简单的指令,它将负责为您执行buttonset()作业。它看起来像

directive('buttonset', function() {
    return function(scope, elm, attrs) {
      elm.buttonset();
    };
  });

在你的HTML中,你可以做到

<div class="test" ng-repeat="group in calc" buttonset>

现在你的代码不依赖你的html中class =“test”的存在。

在您的情况下发生的事情是JQuery UI正在改变DOM。它隐藏了你的单选按钮并放入其他html元素(重新设置无线电组)。单击此新窗口小部件时,JQuery UI代码会将该单击传播到对应的单选按钮。

如果JQuery UI暴露了一个事件或类似的东西,那么我们就可以了解它,并且从Angular你可以调用$scope.$apply();。但是,不幸的是,这似乎并非如此(除非我弄错了)。

如果你真的需要JQuery UI的外观,你可以编写自己的代码(在JQuery UI操作DOM之后复制粘贴特定的HTML部分)。使用JQuery UI中的样式并编写自己的逻辑。 Angular使编写自己的逻辑非常容易。

答案 1 :(得分:1)

让jQuery UI首先修改DOM,然后让AngularJS进行DOM操作。这样,Angular将绑定到修改后的DOM元素。 我将您的JavaScript放在页面底部,以便在不需要超时的情况下使用它:

</body>
<script type="text/javascript">
    $(".test").buttonset()  // allow jQuery UI to manipulate the DOM here, first!
    function ExampleCtrl($scope) {
        $scope.list = [ ... ];
        $scope.calc = [ [...] ];
    }
</script>

更新:正如@ Chas.Owens指出的那样,这不起作用。尽管数据绑定工作正常,但UI仍然存在。如果看起来如果jQuery UI首先修改DOM(如上所示),AngularJS数据绑定可以工作,但它会以某种方式破坏UI。如果AngularJS首先修改DOM(原始问题),则AngularJS数据绑定不起作用(可能是因为buttonset在标签的文本周围添加了额外的&lt; span&gt;),但UI可以工作。

相关问题