kramer65 kramer65 - 5 months ago 32
Javascript Question

Why doesn't my ng-model update with Typeahead in Firefox?

In a website I'm building with AngularJS I've got an input with a typeahead below for which I use angular-typeahead. It works fine in Chrome, Opera and Safari but not in Firefox. The problem seems to be that in Firefox the model isn't updating when I click the typeahead suggestion.

My html looks like this:

<input class="typeahead" sf-typeahead type="text" datasets="userDataset" ng-model="searchUser" >
<button ng-click="sendToUser(searchUser.id)" class="btn">Send</button>


and in my controller I have this simple function:

$scope.sendToUser = function(userId){
console.log(userId);
// More code here..
}


In Chrome, Opera and Safari it logs an int for the
userId
, but in Firefox it just logs
undefined
.

I made a plunker for it here to show what I mean (search for "one", or "two").

It works in Chrome, Opera and Safari, but in Firefox it somehow shows
undefined
in the console. The extra weird thing is that it only shows
undefined
the first time. If you select something a second time it does work.

Does anybody know why this doesn't work in Firefox, and most importantly, how I can solve it? All tips are welcome!

Answer

This was an interesting Dilemma.

  • the TypeAhead sets the ng-model value to an object once selected

  • Upon any event (like click) that runs the digest cycle, the framework enforces the ng-model binding,assigning the model value a string bound to the input.

  • FireFox, unlike Chrome seems to enforce this behavior. Chrome inputs probably allow for object value setting (just a guess).


The work around is to change your output binding:

<input class="typeahead" sf-typeahead type="text"  datasets="userDataset" 
outputval="searchUser" ng-model="a" options="exampleOptions">

The outputval is our expected value. I bound to a random scope variable a because the directive expects and uses a model binding.

Inside the directive, I changed the updateScope function to set the selected value to scope.outputval and commented out the assignment to Model.

    function updateScope (object, suggestion, dataset) {
      scope.$apply(function () {
        var newViewValue = (angular.isDefined(scope.suggestionKey)) ?
            suggestion[scope.suggestionKey] : suggestion;
        console.log(newViewValue);    
        //ngModel.$setViewValue(newViewValue);
        scope.outputval = newViewValue;
      });
    }

Try my Plunker!