Scooter
Scooter

Reputation: 1069

AngularJS ng-repeat slightly slow updating

I'm attempting to create a line numbering system for a textarea element using Angular's ng-repeat directive. Essentially, using the ng-keyup event, I'm calling a function updateLineNumbers() that calculates the total amount of lines in the textarea and adds to an array of line numbers attached to the $scope if needed.

angular.module('editorApp')
.controller('LineNumberController', ['$scope', function($scope){
    $scope.lines = [1];
    $scope.updateLineNumber = function(){
        var text = $("#editor").val();   
        var lines = text.split(/\r|\r\n|\n/);
        var count = lines.length;
        console.log(count);
        if(count > $scope.lines.length){
            console.log("adding line...");
            var len = $scope.lines.length;
            var linesToAdd = count - len;
            console.log("lines to add: " + linesToAdd);
            for(var i = 0; i < linesToAdd; i++){
                console.log('adding line number: ' + (i + $scope.lines[len - 1] + 1));
                $scope.lines.push(i + $scope.lines[len - 1] + 1);
            }
        }
    }
}]);

The console log statements are just for debugging purposes btw. This works fine, and everything displays how i want it, however I notice its just slightly slow. The new line number appears just a moment behind the cursor making it to the next line. I know its picky, but this bothers me and I was wondering if there was a solution for this in Angular, or if I should just use JQuery.

Here is the html code:

<div class="main-editor" ng-controller="LineNumberController">
      <div class="line-numbers">
        <div ng-repeat="line in lines" id="line{{ $index + 1 }}">{{ $index + 1 }}</div>
      </div>
      <div class="editor-container">
        <textarea name="editor" id="editor" cols="30" rows="10" ng-keyup="updateLineNumber()"></textarea>
      </div>
    </div>

Here's the plunkr http://plnkr.co/edit/0POJTx0p4rtfwOAaNRPb?p=preview

Upvotes: 0

Views: 375

Answers (1)

charlietfl
charlietfl

Reputation: 171669

Here's a simpler approach using a watch on ng-model

The important part is using ng-trim="false" otherwise ng-model will trim breaks after last character

  var lineCount = 1;
  $scope.$watch('model.editor', function(nV, oV) {
    if (!nV) {
      $scope.lines = [1];    
    } else {
      var lines = nV.split(/\r|\r\n|\n/);
      // create new array if number of lines changed
      if (lines.length !== lineCount) {
        $scope.lines = lines.map(function(_, i) {
          return i + 1
        });
        lineCount = lines.length;
      }
    }
  });

View

  <div class="line-numbers">
    <div ng-repeat="line in lines" id="line{{ $index + 1 }}">{{ line }}</div>
  </div>
  <div class="editor-container">
    <textarea name="editor" id="editor" cols="30" rows="10" ng-model="model.editor" ng-trim="false"></textarea>
  </div>

Note this works also while removing data.

DEMO

Upvotes: 1

Related Questions