Using ng-pattern with ng-model parsing/formatting

2.7k Views Asked by At

I'm trying to be real fancy with angular inputs by using both ng-pattern and ng-model parsing together. The regex I put in ng-pattern works fine on regex101.com, and even logging it in my app it works great. When using it in ng-pattern however, its saying my input is invalid though when it should not be. I'm wondering when ng-pattern does its thing in relation to when ngModel.$parsers/ngModel.$formatters are doing their thing, because i could see that causing it to fail. Here's some code:

Here's the ngModel parsing directive:

UI.directive('formatSeconds', function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {

            var padZero = function (num, size) {
                return ('00' + num).substr(-size);
            };

            var formatSeconds = function (seconds) {
                var min = Math.floor(seconds / 60);
                var sec = Math.floor(seconds % 60);
                var ms = Math.round(((seconds % 60) - sec) * 1000);
                return min + ':' + padZero(sec, 2) + ':' + padZero(ms, 3);
            };

            var parseTime = function (time) {
                time = time.split(':');
                var min = parseInt(time[0] || 0);
                var sec = parseInt(time[1] || 0);
                var ms = parseInt(time[2] || 0);
                return min * 60 + sec + (ms / 1000);
            };

            ngModel.$parsers.push(parseTime);
            ngModel.$formatters.push(formatSeconds);
        }
    };
});

Here's my regex in my controller:

$scope.timeRegex = /^([0-9]+)?\:([0-5][0-9])\:?([0-9]{3})?$/;

And here's the relevant part of my view:

<tbody ng-form name="syncForm">
    <tr class="timing-entry" ng-repeat="entry in scenario.syncManifest">
        <td>
            <input type="text" ng-attr-name="{{'time' + $index}}" required ng-model="entry.time" format-seconds ng-pattern="timeRegex" />
        </td>
    </tr>
</tbody>

The time in entry is in seconds, so the formatter puts it in 0:00:000 format. Then I hoped the ng-pattern would kick in and say yes! valid! But I'm wondering if it is running when the time property is still in 0.000 format before parsing.

1

There are 1 best solutions below

2
On BEST ANSWER

Angular validation is performed upon the ng-model value, that is to say:

  • When a value is inputted into the view, the $parsers will run and the inputted value will be transformed into how you want it stored in the ng-model. In this case, thats a number representing the number of seconds. Then the ng-pattern will work on that value - if it passes validation, ng-model will be set.
  • When the value is set from the controller, the ng-pattern will go to work on that raw ng-model value. I believe the $formatters will run and the formatted $viewValue will be sent to the view regardless of the validation result.

Either way - in your example, ng-pattern will be working on the integer value of seconds, not the formatted value displayed in the control.