简体   繁体   中英

ng-pattern not working inside directive

I'm trying to wrap an <input> in a directive so that I can handle date validation and convert it from a string to an actual Date object and maintain the Date version in the original scope. This interaction is working as expected. But the ng-pattern on the <input> element isn't acting right. It is never invalidating the <input> , regardless of what is entered.

HTML

<pl-date date="date"></pl-date>

JS

.directive("plDate", function (dateFilter) {
  return {
    restrict: 'E',
    replace: true,
    template: '<input id="birthDateDir" name="birthDate" type="text" ng-pattern="{{getDatePattern()}}" ng-model="dateInput">',
    scope: {
        date: '='
    },
    link: function (scope) {
        scope.dateInput = dateFilter(scope.date, 'MM/dd/yyyy');

        scope.$watch('date', function (newVal) {
            if (newVal !== scope.tmp) {
                if (!newVal) {
                    scope.dateInput = null;
                } else {
                    scope.dateInput = dateFilter(scope.date, 'MM/dd/yyyy');
                }
            }
        });

        scope.getDatePattern = function () {
            var exp = '/';

            // Removed for brevity

            exp += '/';

            return exp;
        };

        scope.$watch('dateInput', function (newVal) {
            if (newVal !== null) {
                scope.date = new Date(newVal);
                scope.tmp = scope.date;
            }
        });
    }
};

JSFiddle here: https://jsfiddle.net/e5qu5rgy/1/

Any help at all is greatly appreciated!

So it looks like the problem can be fixed by changing the link function for the directive to be a controller function instead, as follows

.directive("plDate", function (dateFilter) {
    return {
        restrict: 'E',
        replace: true,
        template: '<input id="birthDateDir" name="birthDate" class="formField" type="text" ng-pattern="{{getDatePattern()}}" ng-model="dateInput">',
        scope: {
            date: '='
        },
        controller: function ($scope, $element, $attrs) {
            $scope.dateInput = dateFilter($scope.date, 'MM/dd/yyyy');

            $scope.$watch('date', function (newVal) {
                if (newVal !== $scope.tmp) {
                    if (!newVal) {
                        $scope.dateInput = null;
                    } else if (newVal.toString() !== "Invalid Date") {
                        $scope.dateInput = dateFilter($scope.date, 'MM/dd/yyyy');
                    }
                }
            });

            $scope.getDatePattern = function() {
                var exp = '/';

                // Months with 31 days
                exp += '^(0?[13578]|1[02])[\/.](0?[1-9]|[12][0-9]|3[01])[\/.](18|19|20)[0-9]{2}$';

                //Months with 30 days
                exp += '|^(0?[469]|11)[\/.](0?[1-9]|[12][0-9]|30)[\/.](18|19|20)[0-9]{2}$';

                // February in a normal year
                exp += '|^(0?2)[\/.](0?[1-9]|1[0-9]|2[0-8])[\/.](18|19|20)[0-9]{2}$';

                // February in a leap year
                exp += '|^(0?2)[\/.]29[\/.](((18|19|20)(04|08|[2468][048]|[13579][26]))|2000)$';

                exp += '/';

                return exp;
            };

            $scope.$watch('dateInput', function (newVal) {
                if (newVal !== null) {
                    $scope.date = new Date(newVal);
                    $scope.tmp = $scope.date;
                }
            });
        }
    };
});

Before going into production, the controller needs to be changed over to use an array for its arguments to protect against minification.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM