使用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>
如果您通过键入更新文本框,它可以正常工作(您可以看到文本更改)。但是如果你使用向上或向下箭头,模型不会改变。
答案 0 :(得分:7)
迟到的答案,但是...有一个非常简单和干净的“Angular方式”,以确保微调器的spin
事件处理针对ngModel
的更新而不诉诸$apply
(尤其是在不诉诸$parse
或仿真的情况下。)
您需要做的就是定义一个带有两个特征的 very 小指令:
该指令作为要转换为微调器的输入元素的属性放置;以及
该指令配置微调器,使spin
事件侦听器使用ngModel
事件值调用$setViewValue
控制器的spin
方法。
这是指令的明确,微小的荣耀:
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);
}
});
};
});