Search code examples
regexangularjsinputtrimonblur

angularjs: regexp fails onblur


I'd love to detect where a string matches a regexp but this seems to fail on blur. Please see this plunkr.

Here's the js:

 var endsWithPipeOrSpace = /\s+$|\|$/g;

$scope.inputGetFocus = function() {
  $scope.msg = "input gained focus"
  if (endsWithPipeOrSpace.test($scope.newquery)) {
    $scope.msg += " string match";
  } else {
    $scope.msg += " string doesn't match";
  }
}

$scope.inputLostFocus = function() {
  $scope.msg = "input has lost focus"
  if (endsWithPipeOrSpace.test($scope.newquery)) {
    $scope.msg += " string match";
  } else {
    $scope.msg += " string doesn't match";
  }
}


$scope.newQueryModified = function() {
  $scope.msg = "input modified"
  if (endsWithPipeOrSpace.test($scope.newquery)) {
    $scope.msg += " string match";
  } else {
    $scope.msg += " string doesn't match";
  }
}

and here's the HTML:
Please note I'm declaring ng-trim="false"

 <input type="text" class="form-control" 
id="newquery" ng-model="newquery" 
placeholder="Enter your query" 
autofocus required autocomplete="off" 
ng-change="newQueryModified()" 
ng-trim="false" 
ng-focus="inputGetFocus()" 
ng-blur="inputLostFocus()">

Solution

  • regexp fails on blur because the lastIndex of endsWithPipeOrSpace has been changed in newQueryModified function.

    Read a bit about RegExp lastIndex property.
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/lastIndex

    The lastIndex is a read/write integer property of regular expressions that specifies the index at which to start the next match.

    When a successfull match happens for regular expression, lastIndex value is changed to length of matched string.
    So here you have to reset the lastIndex value to 0 to test $scope.newquery with endsWithPipeOrSpace like this

    $scope.inputLostFocus = function() {
       $scope.msg = "input has lost focus"
       endsWithPipeOrSpace.lastIndex = 0;          // reset lastIndex here
       if (endsWithPipeOrSpace.test($scope.newquery)) {
           $scope.msg += " string match";
       } else {
           $scope.msg += " string doesn't match";
       }
    }