I'm trying to deal with different behavior of ngModel
in different browsers.
My directive wraps jqueryUI autocomplete and on its select
event it calls ngModel.$setViewValue(selectedItem.id)
. Autocomplete allows user to select item by mouse click or by pressing enter
on the keyboard.
If suggested item is:
{
"name": "Apple",
"id": "1000"
}
I expect after selecting it, the ngModel value will be selected item's id
- 1000
.
In Chrome it works OK - it sets $viewValue
and $modelValue
correctly ($modelValue=1000
).
In Firefox it sets model as in Chrome ($modelValue=1000
), but when I click somewhere else - make blur (then browser probably fires change
event), model changes and it becomes same as visible input value ($modelValue='Apple'
).
In IE 11 it sets model correct only when I select item with mouse click. If I select it by pressing enter
, the model becomes visible input value ($modelValue='Apple'
)
Here is plunkr: http://plnkr.co/edit/o2Jkgprf8EakGqnpu22Y?p=preview
I'd like to reach the same behavior in every browser. How to deal with that problems?
Ok, I think I've made it. The solution is based on Yoshi's comment and it uses local model to keep selected data.
When user selects something, local model is set to selected Object
and $viewValue
is set to the text value of selected item. Then parser sets id
property of local model as $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;
});
Parser function do also one important thing. Because it's run when user type something or on the change
event (that was the problem in firefox!), it checks if the value is same as current local model's text value, and if not it changes local model into this value. It means that if parser function is run by change
event value would be the same as text value, so $modelValue
is not changed, but if user type something model is updated to the typed value (it becomes String
).
Validator function checks if local model is an Object
. If not it means that field is invalid so by default its $modelValue
disappears.
Here is the plunkr: http://plnkr.co/edit/2ZkXFvgLIwDljfJoyeJ1?p=preview
(In formatter function I return that what comes, so $viewValue
is temporarily an Object
but then in $render
method I call $setViewValue
to set $viewValue
and $modelValue
correctly, so it becomes String
. I heard $setViewValue
should not be run in $render
method, but I don't see other way to set correct $modelValue
when something comes from outside).