Json 加载角度UI引导日期选择器时将日期字符串解析为日期对象

Json 加载角度UI引导日期选择器时将日期字符串解析为日期对象,json,angularjs,datepicker,angular-ui,angular-ui-bootstrap,Json,Angularjs,Datepicker,Angular Ui,Angular Ui Bootstrap,我正在使用Angular UI引导日期选择器: 当我使用从服务器接收的数据呈现表单时,datetime字段有问题。我的输入日期选择器如下所示: <form name="itemForm"> <input type="datetime" class="form-control" id="startedAt" name="startedAt" ng-model="item.startedAt" ng-click="open($e

我正在使用Angular UI引导日期选择器:

当我使用从服务器接收的数据呈现表单时,datetime字段有问题。我的输入日期选择器如下所示:

<form name="itemForm">
    <input type="datetime" class="form-control" id="startedAt" name="startedAt"
           ng-model="item.startedAt"
           ng-click="open($event, 'startedAt')"
           uib-datepicker-popup="yyyy-MM-dd"
           is-open="datepickers.startedAt"
    />
</form>
当我将响应数据分配给模型
$scope.item=response,datepicker输入字段正确呈现(选择了正确的日期,并以我选择的格式正确格式化)。问题是验证没有通过。我得到:

itemForm.startedAt.$invalid == true
我注意到绑定到日期选择器字段的数据应该是
Date
对象,而不是字符串(当我从日期选择器中选择新日期时,
$scope.item.startedAt
是一个
日期

我设法解决了这个问题,并在控制器中执行了以下操作:

$scope.item = response;
$scope.item.startedAt = new Date($scope.item.startedAt);
它是这样工作的。。。但我不希望每次从服务器得到响应时都手动转换字符串do date。我试图创建一个指令,我可以将其分配给datepicker输入字段,以便它为我转换
ng模型

.directive("asDate", function () {
    return {
        require: 'ngModel',
        link: function (scope, element, attrs, modelCtrl) {

            modelCtrl.$formatters.push(function (input) {

                var transformedInput = new Date(input);

                if (transformedInput != input) {
                    modelCtrl.$setViewValue(transformedInput);
                    modelCtrl.$render();
                }

                return transformedInput;
            });
        }
    }
})
它可以工作,因为现在我可以看到
Date
对象,当我在视图中输出模型时:
{{item.startedAt}
。但是,验证仍然失败!我怀疑这是我理解模型和视图之间的数据流动以及UI引导如何与之挂钩的问题


另外,当我将指令从
$formatters.push
更改为
$formatters.unshift
时,验证工作正常,但datepicker不格式化我的日期时间(代替格式良好的yyyy MM dd
我在输入中看到ISO字符串)

这从Angular.UI.Bootstrap v0.13.2(8-2-2015)开始中断 降级到0.13.1行得通,这就是我今天遇到的问题

卫斯理乔说这是故意的

如果有人有建议的话,我准备好了其他支持字符串的日期选择器

…发布这篇文章后不久,我走上了一条我并不引以为傲的非角度路径,但它适用于HTML5 type=“date”和uib datepicker弹出窗口。我有一个正则表达式来确定字符串是否类似于我见过的两种序列化日期格式之一,然后我有一个递归javascript函数来遍历json树并用date()替换这些字符串。您可以在放入$scope(或viewmodel)之前调用它

(我不需要检查字符串长度,但我认为如果字符串显然不是日期,则不运行正则表达式可以节省一些cpu周期)


由于这是angular ui bootstrap datepicker()的故意行为,我最终使用angular service/factory和
moment

服务
dateConverter
可以全局注入以拦截所有HTTP请求/响应,也可以仅在所需的控制器中注入

这里我使用
Restangular
库来处理对RESTAPI的请求,因此使用
response.plain()
方法,它只接受对象属性,而不接受Restangular方法/属性

var Services = angular.module('app.Services', []);

Services
    .factory('dateConverter', ['dateFilter', function (dateFilter) {

        var dateConverter = {};

        dateConverter.prepareResponse = function (response) {
            for(prop in response.plain()) {
                if (response.hasOwnProperty(prop)) {
                    if(moment(response[prop], moment.ISO_8601, true).isValid()) {
                        response[prop] = new Date(response[prop]);
                    }
                }
            }
            return response;
        };

        dateConverter.prepareRequest = function (item) {
            for(prop in item.plain()) {
                if (item.hasOwnProperty(prop)) {
                    if(angular.isDate(item[prop])){
                         item[prop] = dateFilter(item[prop] , "yyyy-MM-ddTHH:mm:ssZ")
                    }
                }
            }
            return item;
        };

        return dateConverter;
    }])
;

您可以在Restanglar transformer中将字符串转换为日期,如下所示

RestangularConfigurer
  .addElementTransformer('<RESTRESOURCENAME>', false, function (element) {
      element.createDate = new Date(element.createDate);
      return element;
  })
RestangularConfigurer
.addElementTransformer(“”,false,函数(元素){
element.createDate=新日期(element.createDate);
返回元素;
})

Aww老兄,我们遇到了完全相同的问题@VictorParmar目前我是这样做的——从服务器接收时将响应字符串转换为日期对象。以及在发送到服务器时将日期对象转换为字符串。所有这些都是在角度控制器中手动完成的。也许我会将这个逻辑提取为Angular服务,但我认为它不可能与directiveyeah一起加入俱乐部-我们最终做了同样的事情:)当你在循环中使用javascript时,你可能也应该使用hasOwnProperty()如何使用它有任何指导吗?
//2015-10-01T00:00:00-04:00
//2015-11-20T18:15:56.6229516-05:00
var isDate = new RegExp("\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d{7})?-\\d{2}:00");

function fixDates(json) {
    for (i in json)
        if (typeof (json[i]) == "object")
            fixDates(json[i]);
        else if (typeof (json[i]) == "string" && (json[i].length == 25 || json[i].length == 33) && isDate.test(json[i]))
            json[i] = new Date(json[i]);
};
var Services = angular.module('app.Services', []);

Services
    .factory('dateConverter', ['dateFilter', function (dateFilter) {

        var dateConverter = {};

        dateConverter.prepareResponse = function (response) {
            for(prop in response.plain()) {
                if (response.hasOwnProperty(prop)) {
                    if(moment(response[prop], moment.ISO_8601, true).isValid()) {
                        response[prop] = new Date(response[prop]);
                    }
                }
            }
            return response;
        };

        dateConverter.prepareRequest = function (item) {
            for(prop in item.plain()) {
                if (item.hasOwnProperty(prop)) {
                    if(angular.isDate(item[prop])){
                         item[prop] = dateFilter(item[prop] , "yyyy-MM-ddTHH:mm:ssZ")
                    }
                }
            }
            return item;
        };

        return dateConverter;
    }])
;
RestangularConfigurer
  .addElementTransformer('<RESTRESOURCENAME>', false, function (element) {
      element.createDate = new Date(element.createDate);
      return element;
  })