ngModel——如何处理它在不同浏览器中的不同行为
ngModel - How to deal with its different behavior in different browsers?
我正在尝试处理ngModel
在不同浏览器中的不同行为。
我的指令包装jqueryUI自动完成,并在其select
事件中调用ngModel.$setViewValue(selectedItem.id)
。自动补全允许用户通过鼠标点击或按键盘上的enter
键来选择项目。
如果建议项目为:
{
"name": "Apple",
"id": "1000"
}
我希望在选择它之后,ngModel的值将是被选中项目的id
- 1000
。
在Chrome中它工作正常-它设置
$viewValue
和$modelValue
正确($modelValue=1000
)。在Firefox中它设置模型为Chrome (
$modelValue=1000
),但当我点击其他地方-使模糊(然后浏览器可能触发change
事件),模型改变,它变得与可见输入值($modelValue='Apple'
)相同。在IE 11中,只有当我用鼠标点击选择项目时才会设置模型正确。如果我按下
enter
选择它,模型变成可见输入值($modelValue='Apple'
)
这是plunkr: http://plnkr.co/edit/o2Jkgprf8EakGqnpu22Y?p=preview
我想在每个浏览器中都达到相同的行为。如何处理这些问题?
这似乎与http://bugs.jqueryui.com/ticket/8878
有关正如上面的链接所指出的,更改事件仅在Firefox中触发,而在Chrome中不会触发。所以在你的例子中,$setViewValue在点击外部时再次被触发,模型值被设置为"Apple"。
有自动完成jquery ui小部件的更改回调。要处理这两种情况/浏览器可能是你必须显式地设置视图值在这个回调(它工作)。http://plnkr.co/edit/GFxhzwieBJTSL8zjSPSZ?p =
预览 link: function(scope, elem, attrs, ngModel) {
elem.on('change', function(){
// This will not be printed in Chrome and only on firefox
console.log('change');
});
select: function(event, ui) {
ngModel.$setViewValue(ui.item.data.id);
scope.$apply();
},
// To handle firefox browser were change event is triggered
// when clicked outside/blur
change: function(event, ui) {
ngModel.$setViewValue(ui.item.data.id);
scope.$apply();
}
好了,我想我做到了。解决方案是基于Yoshi的评论,它使用本地模型来保存选定的数据。
当用户选择某项时,本地模型设置为所选Object
, $viewValue
设置为所选项的文本值。解析器将局部模型的id
属性设置为$modelValue
。
select: function(event, ui) {
if(ui.item && ui.item.data){
model = ui.item.data
ngModel.$setViewValue(model.name);
scope.$apply();
}
}
ngModel.$parsers.push(function(value) {
if(_.isObject(model) && value!==model.name){
model = value;
return model;
}
return model.id;
});
解析器函数还做一件重要的事情。因为它是在用户输入内容或change
事件时运行的(这是firefox中的问题!),它检查该值是否与当前本地模型的文本值相同,如果不相同,它将本地模型更改为此值。这意味着如果解析器函数由change
运行,事件值将与文本值相同,因此$modelValue
不会改变,但如果用户类型模型更新为类型值(它变成String
)。
Validator函数检查本地模型是否为Object
。如果不是,则表示该字段无效,因此默认情况下其$modelValue
将消失。
这是plunkr:http://plnkr.co/edit/2ZkXFvgLIwDljfJoyeJ1?p=preview
(在formatter函数中,我返回来的是什么,因此$viewValue
暂时是Object
,但随后在$render
方法中,我调用$setViewValue
来正确设置$viewValue
和$modelValue
,因此它成为String
。我听说$setViewValue
不应该在$render
方法中运行,但我没有看到其他方法来设置正确的$modelValue
当某些东西来自外部时)。
我和ngModelController
和$setViewValue
有过类似的战斗。
最后我寻找其他解决方案。我发现一种非常有效的方法是创建一个新元素作为组件指令,其中包括输入标签作为一个跨包元素。
app.directive('fruitAutocomplete', function($http) {
return {
restrict: 'E',
require: 'ngModel',
transclude: true,
template: '<ng-transclude></ng-transclude>',
link: function(scope, elem, attrs, ngModelController) {
var $input = elem.find('input');
$input.autocomplete({
...
});
}
}
})
在HTML中:
<fruit-autocomplete name="fruit" ng-model="model.fruit">
<input ng-disabled="inputDisabled" placeholder="input fruit"/>
</fruit-autocomplete>
这是一个工作的活塞
有了这个建议的解决方案,你可以将ngModelController
和jQueryUI模态相互作用隔离到它自己的自定义元素,它不会干扰"正常"的<input>
标签,你也不会担心jQueryUI的错误。
通过使用<input>
标签作为跨包元素,你仍然可以从大多数Angular的输入中获益,比如ng-disabled
、placeholder
等…
- 扩展浏览器以处理Apple键盘事件
- 如何在 JavaScript 和浏览器中处理循环引用
- JS浏览器事件处理
- 浏览器无法处理大型 JSON
- 在浏览器中处理流式 JS 内容的最佳方法是什么
- 跨浏览器事件处理程序(添加、删除、触发器)
- 一个浏览器可以处理多少DOM元素
- 将数据发送到python-cgi脚本,以便使用纯javascript从浏览器进行处理
- 浏览器如何处理内联javascript事件
- 为什么函数声明在不同的浏览器中处理方式不同
- 禁用浏览器事件处理程序中的javascript
- Web缓存.如何在浏览器中处理地址初始访问
- 如何以编程方式检测浏览器如何处理window.close() ?
- 是否有一个最大的javascript文件大小,浏览器可以处理什么
- JavaScript对象的大小太大,浏览器无法处理(哦,啪!)
- 浏览器如何处理引号(单引号、双引号)作为表单的输入
- 浏览器不处理报价参数
- 浏览器如何处理源代码中的 CSS 颜色名称
- 跨浏览器事件处理和 jquery 支持
- 浏览器如何处理图像源