ngModel - 如何处理它在不同浏览器中的不同行为?
ngModel - How to deal with its different behavior in different browsers?
我正在尝试处理 ngModel
在不同浏览器中的不同行为。
我的指令包装了 jqueryUI 自动完成并在其 select
事件上调用 ngModel.$setViewValue(selectedItem.id)
。自动完成允许用户通过单击鼠标或按键盘上的 enter
select 项。
如果建议的项目是:
{
"name": "Apple",
"id": "1000"
}
我希望在 selecting 之后,ngModel 值将是 selected 项目的 id
- 1000
.
在 Chrome 中它工作正常 - 它正确设置 $viewValue
和 $modelValue
($modelValue=1000
).
在 Firefox 中,它将模型设置为 Chrome ($modelValue=1000
),但是当我单击其他地方时 - 模糊(然后浏览器可能会触发 change
事件), 模型改变,它变得与可见输入值相同 ($modelValue='Apple'
).
在 IE 11 中,只有当我用鼠标单击 select 项目时,它才会正确设置模型。如果我select它按enter
,模型变成可见输入值($modelValue='Apple'
)
这里是 plunkr:http://plnkr.co/edit/o2Jkgprf8EakGqnpu22Y?p=preview
我想在每个浏览器中实现相同的行为。如何处理这些问题?
这似乎与http://bugs.jqueryui.com/ticket/8878
有关
正如上面link中指出的,change事件只在Firefox中触发,在Chrome中不会触发。因此,在您的情况下,在外部单击时再次触发 $setViewValue 并且模型值设置为 "Apple".
自动完成 jquery ui 小部件有更改回调。要处理这两个 case/browsers 可能您必须在此回调中再次显式设置视图值(并且有效)。
http://plnkr.co/edit/GFxhzwieBJTSL8zjSPSZ?p=preview
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();
}
我和 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>
这是一个有效的 Plunker
使用这个建议的解决方案,您可以将 ngModelController
和 jQueryUI 模态相互作用隔离到它自己的自定义元素中,并且它不会干扰 "normal" <input>
标记,您也不会关注 jQueryUI 错误。
通过使用 <input>
标签作为嵌入元素,您仍然可以从大多数 Angular 输入内容中受益,例如 ng-disabled
、placeholder
等...
好的,我想我做到了。该解决方案基于 并使用本地模型来保留选定的数据。
当用户选择某些东西时,本地模型被设置为选中的 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 中的问题!),它检查该值是否与当前本地模型的文本值相同,如果不相同,它会更改本地模型到这个值。这意味着如果解析器函数是 运行 by change
事件值将与文本值相同,因此 $modelValue
不会更改,但是如果用户键入某些内容,模型将更新为键入的值(变成 String
)。
验证器函数检查本地模型是否为 Object
。如果不是,则表示该字段无效,因此默认情况下其 $modelValue
消失。
这里是 plunkr:
http://plnkr.co/edit/2ZkXFvgLIwDljfJoyeJ1?p=preview
(在格式化程序函数中,我 return 来了,所以 $viewValue
暂时是一个 Object
但随后在 $render
方法中我调用 $setViewValue
到正确设置 $viewValue
和 $modelValue
,所以它变成了 String
。我听说 $setViewValue
在 $render
方法中不应该是 运行,但我不知道当有东西来自外部时,我看不到其他设置正确 $modelValue
的方法。
我正在尝试处理 ngModel
在不同浏览器中的不同行为。
我的指令包装了 jqueryUI 自动完成并在其 select
事件上调用 ngModel.$setViewValue(selectedItem.id)
。自动完成允许用户通过单击鼠标或按键盘上的 enter
select 项。
如果建议的项目是:
{
"name": "Apple",
"id": "1000"
}
我希望在 selecting 之后,ngModel 值将是 selected 项目的 id
- 1000
.
在 Chrome 中它工作正常 - 它正确设置
$viewValue
和$modelValue
($modelValue=1000
).在 Firefox 中,它将模型设置为 Chrome (
$modelValue=1000
),但是当我单击其他地方时 - 模糊(然后浏览器可能会触发change
事件), 模型改变,它变得与可见输入值相同 ($modelValue='Apple'
).在 IE 11 中,只有当我用鼠标单击 select 项目时,它才会正确设置模型。如果我select它按
enter
,模型变成可见输入值($modelValue='Apple'
)
这里是 plunkr:http://plnkr.co/edit/o2Jkgprf8EakGqnpu22Y?p=preview
我想在每个浏览器中实现相同的行为。如何处理这些问题?
这似乎与http://bugs.jqueryui.com/ticket/8878
有关正如上面link中指出的,change事件只在Firefox中触发,在Chrome中不会触发。因此,在您的情况下,在外部单击时再次触发 $setViewValue 并且模型值设置为 "Apple".
自动完成 jquery ui 小部件有更改回调。要处理这两个 case/browsers 可能您必须在此回调中再次显式设置视图值(并且有效)。
http://plnkr.co/edit/GFxhzwieBJTSL8zjSPSZ?p=preview
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();
}
我和 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>
这是一个有效的 Plunker
使用这个建议的解决方案,您可以将 ngModelController
和 jQueryUI 模态相互作用隔离到它自己的自定义元素中,并且它不会干扰 "normal" <input>
标记,您也不会关注 jQueryUI 错误。
通过使用 <input>
标签作为嵌入元素,您仍然可以从大多数 Angular 输入内容中受益,例如 ng-disabled
、placeholder
等...
好的,我想我做到了。该解决方案基于
当用户选择某些东西时,本地模型被设置为选中的 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 中的问题!),它检查该值是否与当前本地模型的文本值相同,如果不相同,它会更改本地模型到这个值。这意味着如果解析器函数是 运行 by change
事件值将与文本值相同,因此 $modelValue
不会更改,但是如果用户键入某些内容,模型将更新为键入的值(变成 String
)。
验证器函数检查本地模型是否为 Object
。如果不是,则表示该字段无效,因此默认情况下其 $modelValue
消失。
这里是 plunkr: http://plnkr.co/edit/2ZkXFvgLIwDljfJoyeJ1?p=preview
(在格式化程序函数中,我 return 来了,所以 $viewValue
暂时是一个 Object
但随后在 $render
方法中我调用 $setViewValue
到正确设置 $viewValue
和 $modelValue
,所以它变成了 String
。我听说 $setViewValue
在 $render
方法中不应该是 运行,但我不知道当有东西来自外部时,我看不到其他设置正确 $modelValue
的方法。