AngularJS: Updating an input with a dynamic ng-model blurs on each key press

All we need is an easy explanation of the problem, so here it is.

jsFiddle to demonstrate the problem: http://jsfiddle.net/yoxigen/xxTJc/

I’m building a small form to edit all of an object’s properties. For that, I have a repeater for the properties. Each property has its input:

<ul ng-controller="myController">
   <li ng-repeat="(property, value) in obj">
       <input ng-model="obj[property]"/><span>{{value}}</span>
   </li>
</ul>

Each time a key is pressed in an input, the value next to it updates properly, but the input loses focus. Any idea how this can be fixed?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I wish there was a way to postpone the regeneration until I’m done
editing.

You might be able to do that. Just make a custom directive that blasts away the AngularJS events and listen to “change” instead. Here is a sample of what that custom directive might look like:

YourModule.directive('updateModelOnBlur', function() {
  return {
    restrict: 'A',
    require: 'ngModel',
    link: function(scope, elm, attr, ngModelCtrl)
    {
      if(attr.type === 'radio' || attr.type === 'checkbox')
      {
        return;
      }

      // Update model on blur only
      elm.unbind('input').unbind('keydown').unbind('change');
      var updateModel = function()
      {
        scope.$apply(function()
        {
          ngModelCtrl.$setViewValue(elm.val());
        });
      };
      elm.bind('blur', updateModel);

      // Not a textarea
      if(elm[0].nodeName.toLowerCase() !== 'textarea')
      {
        // Update model on ENTER
        elm.bind('keydown', function(e)
        {
          e.which == 13 && updateModel();
        });
      }
    }
  };
});

Then on your input:

<input type="text" ng-model="foo" update-model-on-blur />

Method 2

From the google forums:

The problem is that with every change to the model object the
ng-repeat regenerates the whole array and so blurs your input box.
What you need to do is wrap your strings in objects

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply