用 jQuery 设置输入值后更新角度模型

我有一个简单的场景:

使用 jQuery 的 val ()方法更改值的输入元素。

我试图用 jQuery 设置的值更新角度模型。我试图写一个简单的指令,但它不是做我想要的。

下面是指令:

var myApp = angular.module('myApp', []);
myApp.directive('testChange', function() {
return function(scope, element, attrs) {
element.bind('change', function() {
console.log('value changed');
})
}
})

这是 jQuery 部分:

$(function(){
$('button').click(function(){
$('input').val('xxx');
})
})

及 html:

<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input test-change ng-model="foo" />
<span>{{foo}}</span>
</div>
</div>


<button>clickme</button>

这是我尝试的小提琴:
Http://jsfiddle.net/u3pvm/743/

谁能告诉我正确的方向?

188033 次浏览

NgModel 侦听“ input”事件,因此要“修复”代码,您需要在设置值之后触发该事件:

$('button').click(function(){
var input = $('input');
input.val('xxx');
input.trigger('input'); // Use for Chrome/Firefox/Edge
input.trigger('change'); // Use for Chrome/Firefox/Edge + IE11
});

关于这种特殊行为的解释,请看我刚才给出的答案: “ AngularJS 如何在内部捕获“ onclick”、“ onchange”之类的事件?


但不幸的是,这不是你唯一的问题。正如其他文章评论所指出的,以 jQuery 为中心的方法是完全错误的。更多信息请看这篇文章: 如果我有一个 jQuery 背景,我如何“在 AngularJS 中思考”?)。

我认为这里不需要 jQuery。

您可以改用 $看滴答

<div ng-app="myApp">
<div ng-controller="MyCtrl">
<input test-change ng-model="foo" />
<span>\{\{foo}}</span>


<button ng-click=" foo= 'xxx' ">click me</button>
<!-- this changes foo value, you can also call a function from your controller -->
</div>
</div>

在你的控制器中:

$scope.$watch('foo', function(newValue, oldValue) {
console.log(newValue);
console.log(oldValue);
});

您必须使用以下代码来更新特定输入模型的范围,如下所示

$('button').on('click', function(){
var newVal = $(this).data('val');
$('select').val(newVal).change();


var scope = angular.element($("select")).scope();
scope.$apply(function(){
scope.selectValue = newVal;
});
});

希望这对谁有用。

我无法得到的 jQuery('#myInputElement').trigger('input')事件被拾起我的角度应用程序。

然而,我能够得到 angular.element(jQuery('#myInputElement')).triggerHandler('input')被拾起。

我为 jQuery 编写了这个小插件,如果存在的话,它会让所有对 .val(value)的调用都更新 angle 元素:

(function($, ng) {
'use strict';


var $val = $.fn.val; // save original jQuery function


// override jQuery function
$.fn.val = function (value) {
// if getter, just return original
if (!arguments.length) {
return $val.call(this);
}


// get result of original function
var result = $val.call(this, value);


// trigger angular input (this[0] is the DOM object)
ng.element(this[0]).triggerHandler('input');


// return the original result
return result;
}
})(window.jQuery, window.angular);

只要在 jQuery 和 angular.js 以及 val(value)更新之后插入这个脚本,就可以很好地运行了。


缩小版:

!function(n,t){"use strict";var r=n.fn.val;n.fn.val=function(n){if(!arguments.length)return r.call(this);var e=r.call(this,n);return t.element(this[0]).triggerHandler("input"),e}}(window.jQuery,window.angular);

例如:

// the function
(function($, ng) {
'use strict';
  

var $val = $.fn.val;
  

$.fn.val = function (value) {
if (!arguments.length) {
return $val.call(this);
}
    

var result = $val.call(this, value);
    

ng.element(this[0]).triggerHandler('input');
    

return result;
    

}
})(window.jQuery, window.angular);


(function(ng){
ng.module('example', [])
.controller('ExampleController', function($scope) {
$scope.output = "output";
      

$scope.change = function() {
$scope.output = "" + $scope.input;
}
});
})(window.angular);


(function($){
$(function() {
var button = $('#button');
  

if (button.length)
console.log('hello, button');
    

button.click(function() {
var input = $('#input');
      

var value = parseInt(input.val());
value = isNaN(value) ? 0 : value;
      

input.val(value + 1);
});
});
})(window.jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div ng-app="example" ng-controller="ExampleController">
<input type="number" id="input" ng-model="input" ng-change="change()" />
<span>\{\{output}}</span>
<button id="button">+</button>
</div>

我通过在操作按钮上添加侦听器对控制器初始化进行了修改:

$(document).on('click', '#action-button', function () {
$timeout(function () {
angular.element($('#input')).triggerHandler('input');
});
});

其他解决方案在我的情况下不起作用。

如果你正在使用 IE,你必须使用: input.touch (“ change”) ;

设置值后添加 .change()

例子: ('id').val.('value').change();

也不要忘记在 html 中添加 onchangeng-change标记

使用 jQuery 触发 input事件的公认答案对我不起作用。创建一个事件并使用本地 JavaScript 进行分派就可以解决这个问题。

$("input")[0].dispatchEvent(new Event("input", { bubbles: true }));

我知道现在回答这个问题有点晚了,但也许我可以节省一些时间。

我一直在处理同样的问题。一旦您更新了来自 jQuery 的输入值,模型将不会被填充。我试过使用触发器事件,但没有结果。

我所做的也许能拯救你的一天。

在 HTML 中的 script 标记中声明一个变量。

比如:

<script>
var inputValue="";


// update that variable using your jQuery function with appropriate value, you want...


</script>

一旦你做到这一点,使用下面的服务的角。

$窗户

现在下面从相同的控制器作用域调用的 getData 函数将提供所需的值。

var myApp = angular.module('myApp', []);


app.controller('imageManagerCtrl',['$scope','$window',function($scope,$window) {


$scope.getData = function () {
console.log("Window value " + $window.inputValue);
}}]);

我这样做是为了能够从外部用 Vanilla/jQuery 更新 ngModel 的值:

function getScope(fieldElement) {
var $scope = angular.element(fieldElement).scope();
var nameScope;
var name = fieldElement.getAttribute('name');
if($scope) {
if($scope.form) {
nameScope = $scope.form[name];
} else if($scope[name]) {
nameScope = $scope[name];
}
}
return nameScope;
}


function setScopeValue(fieldElement, newValue) {
var $scope = getScope(fieldElement);
if($scope) {
$scope.$setViewValue(newValue);
$scope.$validate();
$scope.$render();
}
}


setScopeValue(document.getElementById("fieldId"), "new value");

不是 OP 所要求的,而是对于任何可能正在编写一个通过输入字段并填充所需细节的 用户脚本的灵魂。对我来说没有什么(完全)奏效,但最终还是设法用这种方式完成了:

var el = $('#sp_formfield_fw_ip');
el.val("some value");
angular.element(el).triggerHandler('focus');
angular.element(el).triggerHandler('input');
angular.element(el).triggerHandler('change');
angular.element(el).triggerHandler('blur');

打开开发人员工具,检查 input字段中添加的事件。在那里,我找到了所有这些(在我的案例中) : focusinputchangeblur