【问题标题】:AngularJS - set validity of wrapped directivesAngularJS - 设置包装指令的有效性
【发布时间】:2015-11-23 22:03:25
【问题描述】:

我正在研究一个简单的指令 - 日期/时间选择器。它包装了角度材料日期选择器和两个额外的选择(小时和分钟),构建日期并通过ngModel 公开它。

我已经实现了验证逻辑,用户可以提供最小值和最大值,如果选择的日期和时间超出范围,则模型有效性设置为 false。

这是指令的标记和代码:

<div layout="column">    
    <div layout="row">
        <md-datepicker name="selectedDatePicker" ng-model="selectedDate" flex="50" flex-order="1"></md-datepicker>
        <md-input-container flex="25" flex-order="2">
            <label>Hour</label>
            <md-select ng-model="selectedHour">
                <md-option ng-repeat="hour in hours" value="{{hour}}">
                    {{hour}}
                </md-option>
            </md-select>
        </md-input-container>
        <md-input-container flex="25" flex-order="2">
            <label>Minute</label>
            <md-select ng-model="selectedMinute">
                <md-option ng-repeat="minute in minutes" value="{{minute}}">
                    {{minute}}
                </md-option>
            </md-select>
        </md-input-container>
    </div>
    <div layout="row">
        <ng-transclude></ng-transclude>
    </div>
</div>

angular.module('myApp')
    .directive('jcdatetimepicker', function ($parse) {

        var link = function (scope, iElement, iAttrs, ngModel) {

            var initValue = scope.ngModel;
            setDateTime(initValue);

            ngModel.$parsers.push(validateInput);
            ngModel.$formatters.push(validateInput);

            ngModel.$render = function () {
                setDateTime(ngModel.$viewValue);
            }

            scope.$on('jcdatetimepicker:updateModel', function (evt, args) {                
                ngModel.$setViewValue(validateInput(args));
            });

            function validateInput(inputDate){
                var valid = true;                              

                if (angular.isDefined(scope.minValue) && (inputDate < scope.minValue)) {
                    valid = false;
                    ngModel.$setValidity('min', false);
                }
                else {                
                    ngModel.$setValidity('min', true);
                }

                if (angular.isDefined(scope.maxValue) && (inputDate > scope.maxValue)) {
                    valid = false;
                    ngModel.$setValidity('max', false);
                }
                else {
                    ngModel.$setValidity('max', true);
                }
                return valid ? inputDate : undefined;
            }

            function setDateTime(date) {
                if (angular.isDate(date)) {
                    scope.selectedMinute = date.getMinutes();
                    scope.selectedHour = date.getHours();
                    scope.selectedDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
                }                
            }
        };

        return {
            restrict: 'E',
            replace: false,
            transclude: true,
            require: '^ngModel',
            scope: {
                ngModel: '=ngModel',
                minValue: '=min',
                maxValue: '=max'
            },
            controller: 'jcDateTimePickerController',
            link: link,
            templateUrl: 'templates/shared/jcDateTimePicker/jcDatetimePicker.html'            
        }
    }).controller('jcDateTimePickerController', function ($scope, $element) {

        $scope.hours = [];
        $scope.minutes = [];

        $scope.selectedMinute = 0;
        $scope.selectedHour = 12;
        $scope.selectedDate = new Date();
        $scope.isValid = false;
        //initialize hours & minutes
        function init() {
            for (var h = 0; h < 24; h++) {
                $scope.hours.push(h);
            }
            for (var m = 0; m < 60; m++) {
                $scope.minutes.push(m);
            }
        };
        init();

        $scope.$watchGroup(['selectedMinute', 'selectedHour', 'selectedDate'], function (newVals, oldVals, _scope) {
            var minutes = newVals[0];
            var hours = newVals[1];
            var date = newVals[2];

            date.setHours(hours, minutes, 0);
            $scope.$broadcast('jcdatetimepicker:updateModel', date);
        });
    });

在验证方面工作正常 - ngModel 传递给我的指令的模型有效性设置正确。问题是,当所选值无效时,我还想为我的指令包装 mdDatepikcermdSelect 的指令设置有效性 - 这样这些指令的 UI 也将指示无效输入。

但是我不知道如何获取那些包装的指令,例如。 G。日期选择器和修补它的有效性。在单元测试中,我尝试使用隔离范围,但 selectedDatePicker 未定义。

这可能吗?或者是否有可能获得它的ngModel 控制器,并以这种方式设置有效性?

非常感谢任何建议。

【问题讨论】:

    标签: angularjs validation angularjs-directive angular-ngmodel


    【解决方案1】:

    如果你有 mdDatepicker 和 mdSelect 范围的签名,你可以使用:angular.element($("[name='selectedDatePicker']")).scope,然后调用函数或设置放弃你想要的行为所必需的属性。

    我没有尝试过代码,但这是一种可能的方法。

    【讨论】:

    • 这非常有用——我甚至可以抓住ngModel 并使用值/有效性。选择的反应正是我想要的,但 datepicker 有点固执,但主要是造型。
    猜你喜欢
    • 2016-08-11
    • 1970-01-01
    • 2016-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多