JQuery UI Spinner没有以角度更新ng-model

时间:2014-03-19 20:59:51

标签: angularjs jquery-ui

使用jquery-ui微调器时,Angular的ng-model没有更新。

这是jsfiddle http://jsfiddle.net/gCzg7/1/

<div ng-app>

  <div ng-controller="SpinnerCtrl">
    <input type="text" id="spinner" ng-model="spinner"/><br/>
    Value: {{spinner}}
  </div>
</div>

<script>
    $('#spinner').spinner({});
</script>

如果您通过键入更新文本框,它可以正常工作(您可以看到文本更改)。但是如果你使用向上或向下箭头,模型不会改变。

6 个答案:

答案 0 :(得分:7)

迟到的答案,但是...有一个非常简单和干净的“Angular方式”,以确保微调器的spin事件处理针对ngModel的更新而不诉诸$apply(尤其是在不诉诸$parse或仿真的情况下。)

您需要做的就是定义一个带有两个特征的 very 小指令:

  1. 该指令作为要转换为微调器的输入元素的属性放置;以及

  2. 该指令配置微调器,使spin事件侦听器使用ngModel事件值调用$setViewValue控制器的spin方法。

    < / LI>

    这是指令的明确,微小的荣耀:

    function jqSpinner() {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, c) {
                element.spinner({
                    spin: function (event, ui) {
                        c.$setViewValue(ui.value);
                    }
                });
            }
        };
    };
    

    请注意,$setViewValue适用于这种情况:

      

    当输入指令想要更改时,应该调用此方法   视角值;通常,这是在DOM事件中完成的   处理程序。

    以下是指向a working demo的链接。

    如果上面提供的演示链接由于某种原因而死亡,那么这是完整的示例脚本:

    (function () {
        'use strict';
    
        angular.module('ExampleApp', [])
            .controller('ExampleController', ExampleController)
            .directive('jqSpinner', jqSpinner);
    
        function ExampleController() {
            var c = this;
            c.exampleValue = 123;
        };
    
        function jqSpinner() {
            return {
                restrict: 'A',
                require: 'ngModel',
                link: function (scope, element, attrs, c) {
                    element.spinner({
                        spin: function (event, ui) {
                            c.$setViewValue(ui.value);
                        }
                    });
                }
            };
        };
    })();
    

    最小的示例模板:

    <div ng-app="ExampleApp" ng-controller="ExampleController as c">
        <input jq-spinner ng-model="c.exampleValue" />
        <p>{{c.exampleValue}}</p>
    </div>
    

答案 1 :(得分:1)

你的小提琴正在展示别的东西。

除此之外:Angular无法知道从其范围之外发生的任何变化而不知道。 如果从OUTSIDE angular更改角度范围的变量,则需要调用apply() - Method以使Angular识别这些更改。尽管使用角度本身可以轻松实现微调器,但在您的情况下,您必须: 1.在SpinnerCtrl中移动微调器 2.将以下内容添加到SpinnerCtrl:

   $('#spinner').spinner({
      change: function( event, ui ) {
           $scope.apply();
       }
   }

如果你真的需要或想要jQuery-Plugin,那么它最好甚至不能在控制器本身中使用它,而是把它放在一个指令中,因为所有的DOM操作都是在angular中的指令中发生的。但这也是AngularJS-Tutorials也会告诉你的。

答案 2 :(得分:1)

Charminbear对于需要$ scope是正确的。$ apply()。然而,这种方法存在几个问题。变化&#39;事件仅在移除微调器的焦点时触发。因此,您必须单击微调器,然后单击其他位置。 &#39;旋转&#39;每次点击都会触发事件。此外,模型需要在$ scope之前更新。$ apply()被调用。

这是一个有效的jsfiddle http://jsfiddle.net/3PVdE/

$timeout(function () {
        $('#spinner').spinner({
            spin: function (event, ui) {
                var mdlAttr = $(this).attr('ng-model').split(".");

                if (mdlAttr.length > 1) {

                    var objAttr = mdlAttr[mdlAttr.length - 1];
                    var s = $scope[mdlAttr[0]];

                    for (var i = 0; i < mdlAttr.length - 2; i++) {
                        s = s[mdlAttr[i]];
                    }

                    s[objAttr] = ui.value;
                } else {
                    $scope[mdlAttr[0]] = ui.value;
                }

                $scope.$apply();
            }
        }, 0);
    });

这是一个类似的问题和方法https://stackoverflow.com/a/12167566/584761

答案 3 :(得分:1)

正如@Charminbear所说,角度不知道这种变化。 然而问题不是角度没有意识到模型的变化,而是它不知道输入的变化。

这是一个修正:

的指令
directives.directive('numeric', function() {
        return function(scope, element, attrs) {
            $(element).spinner({
                change: function(event, ui) {
                    $(element).change();
                } 
            });
        };
    });

通过运行$(element).change(),您通知角度输入已更改,然后角度更新模型并重新绑定。 注意change会在输入模糊的情况下运行,这可能不是您想要的。

答案 4 :(得分:1)

我知道我迟到了,但我是通过在旋转事件中使用ui.value更新模型来实现的。这是更新后的fiddle

function SpinnerCtrl($scope, $timeout) {
    $timeout(function () {
        $('#spinner').spinner({
            spin: function (event, ui) {
                $scope.spinner = ui.value;
                $scope.$apply();
            }
        }, 0);
    });
}

如果此方法“错误”,我们将不胜感激。

答案 5 :(得分:0)

这是一个像编码器解决方案一样更新模型的解决方案,但它使用$ parse而不是解析ng-model参数本身。

app.directive('spinner', function($parse) {
    return function(scope, element, attrs) {
        $(element).spinner({
            spin: function(event, ui) {
                setTimeout(function() {
                    scope.$apply(function() {
                        scope._spinnerVal = = element.val();
                        $parse(attrs.ngModel + "=_spinnerVal")(scope);
                        delete scope._spinnerVal;
                    });
                }, 0);
            }
        });
    };
});