Search code examples
angularjsfocuslost-focusangularjs-watch

Lose the focus after inserting a letter


I have written a script which represent a json data in 2 ways: JSBin

<!DOCTYPE html>
<html>
  <head>
    <script src="https://handsontable.github.io/ngHandsontable/node_modules/angular/angular.js"></script>
  </head>

  <body ng-app="app">
    <div ng-controller="Ctrl">
      GUI:
      <div ng-repeat="item in data">
        <input ng-model="item.val">
      </div>
      <br><br><br>
      Textarea:<br>
      <textarea rows=10 cols=20 ng-model="dataString"></textarea>
    </div>

  <script>
    var app = angular.module('app', []);
    app.controller('Ctrl', ['$scope', '$filter', function($scope, $filter) {
      $scope.data = [{val: "1"}, {val: "2"}];

      $scope.$watch('data', function(data_new) {
        $scope.dataString = $filter('json')(data_new);
      }, true);

      $scope.$watch('dataString', function(dataString_new) {
        $scope.data = JSON.parse(dataString_new);
      }, true);

    }]);
  </script>
  </body>
</html>

Thus, modifying the value in GUI will change the string in the textarea (because of $watch('data'); and modifying the string in the textarea will change the GUI (because of $watch('dataString')).

However, the problem is that when we change the value in GUI, we lose the focus after inserting a letter.

Does anyone know how to amend this?


Solution

  • So the problem is that you are iterating over an array (ng-repeat) and changeing the items of the array. The items are removed from the DOM and new one are inserted because they are strings and thereby compared by value. This makes you loose focus. It's pretty simple to fix though. Just track by index as the objects are in identical order.

    Change:

    <div ng-repeat="item in data">
    

    To:

    <div ng-repeat="item in data track by $index">