-
Notifications
You must be signed in to change notification settings - Fork 27.3k
$parsers function not triggering every 4th keystroke... #10700

Description
Hello,
I have a text input that has a custom directive that prevents non numeric values while enforcing maxLength and maintaining cursor position.
In the directive, I have added a $parser that applies these constraints to the input before it is saved to the model. However, for some reason, the $parser does not trigger on every 4th keystroke.
If I manually type the number "1" into the field, the $parser will trigger for each keystroke except the 4th one. This means that every 4th keystroke, a letter or extra character can be added. The very next keystroke will again trigger the $parser as expected, which removes any previously entered invalid values, but if another keystroke is not entered, then the invalid values will remain.
UPDATE
Just verified that this is only an issue if I press the same key 4 times (ex: "1,1,1,1" or "b,b,b,b"). If I press different keys (ex: "a,b,c,d" or "1,2,3,4", then the $parser fires for every keystroke, as expected).
<input only-digits="3" type="text" title="Phone Prefix" ng-pattern="/^(?:5(?!55)|([2-46-9]))\d{2}$/" name="phonePrefix" class="form-control" ng-attr-placeholder="{{PlaceHolderText.PhonePrefix}}" ng-model="PhonePrefix" required>
(function ()
{
'use strict';
angular.module("mph.directives").directive('onlyDigits', function ()
{
return {
restrict: 'A',
require: '?ngModel',
scope: {
onlyDigits: "="
},
link: function ($scope, element, attrs, ngModel)
{
if (!ngModel) { return; }
var _stripAlpha = function (newValue)
{
if (newValue == null) { return null; }
var _el = element[0];
var _maxLength = $scope.onlyDigits;
var _strippedValue = newValue.replace(/[^\d]+/g, '');
var _cursorPosition = _el.selectionStart;
if (_strippedValue != newValue)
{
//recalculates cursor position to where it should be after all non-numeric characters are stripped away
_cursorPosition = (_el.selectionStart - (newValue.length - _strippedValue.length));
}
if (_strippedValue.length > _maxLength)
{
//strips out any extra digits and re-calculates cursor position
var _digits = _strippedValue.split("");
var _diff = _digits.length - _maxLength;
_cursorPosition -= _diff;
_digits.splice(_cursorPosition, _diff);
_strippedValue = _digits.join("");
}
//updates input field to reflect corrected value
element.val(_strippedValue);
//update cursor position based on final calculation
_el.selectionStart = _el.selectionEnd = _cursorPosition;
//return corrected value to next $parser in the chain (if exists)
return _strippedValue;
};
ngModel.$parsers.unshift(_stripAlpha);
}
};
});
}());
Any ideas on why this is happening?
Thanks!
Josh