【问题标题】:Bind ng-model holding a timestamp to datetime-local input将持有时间戳的 ng-model 绑定到 datetime-local 输入
【发布时间】:2015-09-14 07:12:43
【问题描述】:

我正在尝试使用代表时间戳的ng-model 呈现<input type="datetime-local> 字段:

<input type="datetime-local" ng-model="object.value">

$scope.object.value = 1433109600000;

控制台显示[ngModel:datefmt] 错误。

如何正确地将$scope.object.value 绑定到输入字段? (时间戳来自嵌套对象中的网络服务)

一些Plnkr:http://plnkr.co/edit/TGpKVNF1tv0b1h6JPBT8?p=preview

【问题讨论】:

    标签: javascript angularjs datetime timestamp angular-ngmodel


    【解决方案1】:

    必须是日期对象:

    $scope.object = {
      name: 'Demo',
      value: new Date(1433109600000)
    }
    

    Updated demo

    或者创建一个指令:

    app.directive('bindTimestamp', function () {
      return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ngModel) {
          ngModel.$formatters.push(function (value) {
            return new Date(value);
          });
        }
      };
    });
    

    Directive demo

    【讨论】:

    • 这是一个明确的观点,但如前所述:对象来自网络服务,所以我无法修改值...
    • 为什么不能?例如:return $http.get('...').then(function (result) { result.value = new Date(result.value); return result }); - 这将被修改承诺
    • 另一种方法是为此编写指令。我也写,等一下))
    • 我想一个指令是正确的方法。我真的不知道在返回对象的哪个级别我得到了时间戳并且遍历整个对象是昂贵的
    【解决方案2】:

    完成@karaxuna 的回答,感谢他,以下是完整的指令及其测试:

    directivesApp.directive('bindTimestamp', function () {
        return {
            restrict: 'A',
            require: 'ngModel',
            link: function (scope, element, attrs, ngModel) {
    
                var minDate = attrs.min ? new Date(attrs.min) : null;
                var maxDate = attrs.max ? new Date(attrs.max) : null;
    
                ngModel.$formatters.push(function (value) {
                    var dt = value;
                    if (!angular.isDate(dt) && angular.isNumber(dt)) {
                        // It's a timestamp --> needs to be converted to a <Date>
                        dt = new Date(value);
                    }
                    // truncate 'dt' to second if milliseconds are not to be displayed in input[datetime-local]
                    // dt.setMilliSeconds(0);
                    // truncate 'dt' to minute if seconds are not to be displayed in input[datetime-local]
                    // dt.setSeconds(0);
                    return dt;
                });
    
                // Default validators need to be overriden, otherwise they will always trigger "false" as they expect a <Date> object and not a number.
                var MinMaxValidator = function (modelValue) {
                    var selectedDate = angular.timestampToDate(modelValue, scope.truncateSeconds);
                    this.validate = function (validateThreshold) {
                        if (angular.isDate(selectedDate)) {
                            return validateThreshold(selectedDate);
                        }
                        return true;
                    };
                };
    
                if (ngModel.$validators.min && minDate !== null) {
                    ngModel.$validators.min = function (modelValue) {
                        return new MinMaxValidator(modelValue).validate(function (selectedDate) {
                            return minDate <= selectedDate;
                        });
                    };
                }
    
                if (ngModel.$validators.max && maxDate !== null) {
                    ngModel.$validators.max = function (modelValue) {
                        return new MinMaxValidator(modelValue).validate(function (selectedDate) {
                            return maxDate >= selectedDate;
                        });
                    };
                }
            }
        };
    });
    

    茉莉花测试: describe('bindTimestamp : 时间戳', function () {

        // 2016-02-19 09:56:51.396ms
        var dt = 1455872211396;
    
        function buildInputDateElement(inputType) {
            var element = angular.element('<input type="' + inputType + '" ng-model="myDate" bind-timestamp>');
            $compile(element)($scope);
            $scope.$digest();
            return element;
        }
    
        it('bindTimestamp : input[date]', function () {
    
            var formatedDate = '2016-02-19';
    
            /** A timestamp */
            $scope.myDate = dt;
            var element = buildInputDateElement("date");
            expect(element.val()).toEqual(formatedDate);
    
            //** Already a <Date> */
            $scope.myDate = new Date(dt);
            element = buildInputDateElement("date");
            expect(element.val()).toEqual(formatedDate);
        });
    
        it('bindTimestamp : input[datetime-local]', function () {
    
            var formatedDate = '2016-02-19T09:56:51.396';
    
            /** A timestamp */
            $scope.myDate = dt;
            var element = buildInputDateElement("datetime-local");
    
            expect(element.val()).toEqual(formatedDate);
    
            /** Already a <Date> */
            $scope.myDate = new Date(dt);
            element = buildInputDateElement("datetime-local");
            expect(element.val()).toEqual(formatedDate);
        });
    });
    

    【讨论】:

      猜你喜欢
      • 2021-04-03
      • 2019-08-24
      • 1970-01-01
      • 2016-11-18
      • 2015-05-11
      • 2021-11-01
      • 2014-09-28
      • 1970-01-01
      • 2021-01-19
      相关资源
      最近更新 更多