如何为 angular material datepicker 格式化 ng-model 字符串
How to format ng-model string to date for angular material datepicker
我有一个 mongoose 连接到包含集合中的 Date 对象的数据库。我想使用 Angular Material 的 DatePicker
控件查看这些日期对象。 Date 对象遵循 ISO 字符串格式.
这是一个代码片段:
<md-datepicker
ng-model="license.expirationdate" md-placeholder="Enter date">
</md-datepicker>
我收到以下错误:
md-datepicker
的 ng-model
必须是 Date 实例。
在研究时,我发现您可以使用过滤器来创建 Date 实例,但这对我不起作用 -> 我收到一条错误消息,指出使用简单过滤器时模型值不可分配。过滤器只是根据字符串输入返回一个新的 Date 对象。
如何将字符串格式化为 Date 对象,同时仍允许 ng-model
更改?
编辑:猫鼬的模式
var Schema = mongoose.Schema;
var Schema = mongoose.Schema;
var modelschema = new Schema({
name : String,
licensetype : String,
activationcount : Number,
expirationdate: Date,
key : String
})
这是填充架构的快速路由
app.post('/licenses', function (req, res) {
console.log(req.body.expirationDate);
License.create({
name: req.body.licenseName,
licensetype: req.body.licenseType,
activationcount: 0,
expirationdate: req.body.expirationDate,
key: "123456"
}, function (err, license) {
if (err) {
res.send(err);
console.log(err);
}
//Send user back to main page
res.writeHead(301, {
'Location': '/',
'Content-Type': 'text/plain'
});
res.end();
}
)
});
这是一个例子:
标记:
<div ng-controller="MyCtrl">
<md-datepicker ng-model="dt" md-placeholder="Enter date" ng-change="license.expirationdate = dt.toISOString()">
</md-datepicker>
{{license.expirationdate}}
</div>
JavaScript:
app.controller('MyCtrl', function($scope) {
$scope.license = {
expirationdate: '2015-12-15T23:00:00.000Z'
};
$scope.dt = new Date($scope.license.expirationdate);
});
Fiddle: http://jsfiddle.net/masa671/jm6y12un/
更新:
与ng-repeat
:
标记:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-model="dataMod[$index].dt"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = dataMod[$index].dt.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
JavaScript:
app.controller('MyCtrl', function($scope) {
var i;
$scope.data = [
{ license:
{ expirationdate: '2015-12-15T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-20T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-25T23:00:00.000Z' }
}
];
$scope.dataMod = [];
for (i = 0; i < $scope.data.length; i += 1) {
$scope.dataMod.push({
dt: new Date($scope.data[i].license.expirationdate)
});
}
});
http://jsfiddle.net/katfby9L/1/
// Configure the $httpProvider by adding our date transformer
app.config(["$httpProvider", function ($httpProvider) {
$httpProvider.defaults.transformResponse.push(function(responseData){
convertDateStringsToDates(responseData);
return responseData;
});
}]);
var regexIso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?([0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
function convertDateStringsToDates(input) {
// Ignore things that aren't objects.
if (typeof input !== "object") return input;
for (var key in input) {
if (!input.hasOwnProperty(key)) continue;
var value = input[key];
var match;
// Check for string properties which look like dates.
// TODO: Improve this regex to better match ISO 8601 date strings.
if (typeof value === "string" && (match = value.match(regexIso8601))) {
// Assume that Date.parse can parse ISO 8601 strings, or has been shimmed in older browsers to do so.
var milliseconds = Date.parse(match[0]);
if (!isNaN(milliseconds)) {
input[key] = new Date(milliseconds);
}
} else if (typeof value === "object") {
// Recurse into object
convertDateStringsToDates(value);
}
}
}
这会自动将服务器 JSON 响应中的所有字符串转换为日期
我会这样做:
Html:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-init="date = StrToDate(d.license.expirationdate);"
ng-model="date"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = date.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
在你的控制器中
$scope.StrToDate = function (str) {
return new Date(str);
}
您可以使用自定义过滤器 ng-init 和 ng-change 并在标记中完成此操作。
JavaScript:
app.filter('toDate', function() {
return function(input) {
return new Date(input);
}
})
HTML:
<md-datepicker
ng-init="date = (license.expirationdate | toDate)"
ng-model="date"
ng-change="license.expirationdate = date.toISOString()"
md-placeholder="Enter date">
</md-datepicker>
使用这种方法,您无需将 Controller 代码与 View 逻辑混为一谈。缺点是控制器中对 license.expirationdate 的任何编程更改都不会自动反映在视图中。
我创建了一个自定义指令来为我处理这个问题。我使用了 Sugarjs.com 中的日期 class 以使其像我实现的那样工作。此方法可确保日期始终像日期一样显示,并且不会因涉及 UTC 偏移而跳来跳去。如果您不想限制为 UTC,可以将格式化程序更改为 return new Date(input)
。
angular.module 'app.components'
.directive 'autoChangeStringDates', ->
directive =
restrict: 'A'
require: 'ngModel'
priority: 2000
link: (scope, el, attrs, ngModelController) ->
ngModelController.$formatters.push((input) ->
if typeof input == Date
return input
else
return Date.create(input, {fromUTC: true})
)
return
然后您可以像这样在 HTML 标记中使用它
<md-datepicker ng-model='myModel' auto-change-string-dates></md-datepicker>
我不得不将默认日期设置为从当前日期往后的 6 个月...
在将日期转换为 ISO 格式并返回的相当长的实验之后,我创建了一个我在此处找不到的简单解决方案。
总体思路:今天取时间,以毫秒为单位加/减时间,直到所需日期。
html:
<div flex-gt-xs>
<h4 class="md-title">Date From:</h4>
<md-datepicker ng-model="vm.sixMonthBeforeNow" md-placeholder="Date From:"></md-datepicker>
{{vm.sixMonthBeforeNow}}
</div>
控制器:
vm.sixMonthBeforeNow = new Date((+new Date) - 15778800000); // today - 6 month in ISO format (native for Angular Material Datepicker)
结果:
也许对某人有用...
我有一个 mongoose 连接到包含集合中的 Date 对象的数据库。我想使用 Angular Material 的 DatePicker
控件查看这些日期对象。 Date 对象遵循 ISO 字符串格式.
这是一个代码片段:
<md-datepicker
ng-model="license.expirationdate" md-placeholder="Enter date">
</md-datepicker>
我收到以下错误:
md-datepicker
的 ng-model
必须是 Date 实例。
在研究时,我发现您可以使用过滤器来创建 Date 实例,但这对我不起作用 -> 我收到一条错误消息,指出使用简单过滤器时模型值不可分配。过滤器只是根据字符串输入返回一个新的 Date 对象。
如何将字符串格式化为 Date 对象,同时仍允许 ng-model
更改?
编辑:猫鼬的模式 var Schema = mongoose.Schema;
var Schema = mongoose.Schema;
var modelschema = new Schema({
name : String,
licensetype : String,
activationcount : Number,
expirationdate: Date,
key : String
})
这是填充架构的快速路由
app.post('/licenses', function (req, res) {
console.log(req.body.expirationDate);
License.create({
name: req.body.licenseName,
licensetype: req.body.licenseType,
activationcount: 0,
expirationdate: req.body.expirationDate,
key: "123456"
}, function (err, license) {
if (err) {
res.send(err);
console.log(err);
}
//Send user back to main page
res.writeHead(301, {
'Location': '/',
'Content-Type': 'text/plain'
});
res.end();
}
)
});
这是一个例子:
标记:
<div ng-controller="MyCtrl">
<md-datepicker ng-model="dt" md-placeholder="Enter date" ng-change="license.expirationdate = dt.toISOString()">
</md-datepicker>
{{license.expirationdate}}
</div>
JavaScript:
app.controller('MyCtrl', function($scope) {
$scope.license = {
expirationdate: '2015-12-15T23:00:00.000Z'
};
$scope.dt = new Date($scope.license.expirationdate);
});
Fiddle: http://jsfiddle.net/masa671/jm6y12un/
更新:
与ng-repeat
:
标记:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-model="dataMod[$index].dt"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = dataMod[$index].dt.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
JavaScript:
app.controller('MyCtrl', function($scope) {
var i;
$scope.data = [
{ license:
{ expirationdate: '2015-12-15T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-20T23:00:00.000Z' }
},
{ license:
{ expirationdate: '2015-12-25T23:00:00.000Z' }
}
];
$scope.dataMod = [];
for (i = 0; i < $scope.data.length; i += 1) {
$scope.dataMod.push({
dt: new Date($scope.data[i].license.expirationdate)
});
}
});
http://jsfiddle.net/katfby9L/1/
// Configure the $httpProvider by adding our date transformer
app.config(["$httpProvider", function ($httpProvider) {
$httpProvider.defaults.transformResponse.push(function(responseData){
convertDateStringsToDates(responseData);
return responseData;
});
}]);
var regexIso8601 = /^([\+-]?\d{4}(?!\d{2}\b))((-?)((0[1-9]|1[0-2])(([12]\d|0[1-9]|3[01]))?|W([0-4]\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\d|[12]\d{2}|3([0-5]\d|6[1-6])))([T\s]((([01]\d|2[0-3])((:?)[0-5]\d)?|24\:?00)([\.,]\d+(?!:))?)?([0-5]\d([\.,]\d+)?)?([zZ]|([\+-])([01]\d|2[0-3]):?([0-5]\d)?)?)?)?$/;
function convertDateStringsToDates(input) {
// Ignore things that aren't objects.
if (typeof input !== "object") return input;
for (var key in input) {
if (!input.hasOwnProperty(key)) continue;
var value = input[key];
var match;
// Check for string properties which look like dates.
// TODO: Improve this regex to better match ISO 8601 date strings.
if (typeof value === "string" && (match = value.match(regexIso8601))) {
// Assume that Date.parse can parse ISO 8601 strings, or has been shimmed in older browsers to do so.
var milliseconds = Date.parse(match[0]);
if (!isNaN(milliseconds)) {
input[key] = new Date(milliseconds);
}
} else if (typeof value === "object") {
// Recurse into object
convertDateStringsToDates(value);
}
}
}
这会自动将服务器 JSON 响应中的所有字符串转换为日期
我会这样做:
Html:
<div ng-controller="MyCtrl">
<div ng-repeat="d in data">
<md-datepicker
ng-init="date = StrToDate(d.license.expirationdate);"
ng-model="date"
md-placeholder="Enter date"
ng-change="d.license.expirationdate = date.toISOString()">
</md-datepicker>
{{d.license.expirationdate}}
</div>
</div>
在你的控制器中
$scope.StrToDate = function (str) {
return new Date(str);
}
您可以使用自定义过滤器 ng-init 和 ng-change 并在标记中完成此操作。
JavaScript:
app.filter('toDate', function() {
return function(input) {
return new Date(input);
}
})
HTML:
<md-datepicker
ng-init="date = (license.expirationdate | toDate)"
ng-model="date"
ng-change="license.expirationdate = date.toISOString()"
md-placeholder="Enter date">
</md-datepicker>
使用这种方法,您无需将 Controller 代码与 View 逻辑混为一谈。缺点是控制器中对 license.expirationdate 的任何编程更改都不会自动反映在视图中。
我创建了一个自定义指令来为我处理这个问题。我使用了 Sugarjs.com 中的日期 class 以使其像我实现的那样工作。此方法可确保日期始终像日期一样显示,并且不会因涉及 UTC 偏移而跳来跳去。如果您不想限制为 UTC,可以将格式化程序更改为 return new Date(input)
。
angular.module 'app.components'
.directive 'autoChangeStringDates', ->
directive =
restrict: 'A'
require: 'ngModel'
priority: 2000
link: (scope, el, attrs, ngModelController) ->
ngModelController.$formatters.push((input) ->
if typeof input == Date
return input
else
return Date.create(input, {fromUTC: true})
)
return
然后您可以像这样在 HTML 标记中使用它
<md-datepicker ng-model='myModel' auto-change-string-dates></md-datepicker>
我不得不将默认日期设置为从当前日期往后的 6 个月...
在将日期转换为 ISO 格式并返回的相当长的实验之后,我创建了一个我在此处找不到的简单解决方案。
总体思路:今天取时间,以毫秒为单位加/减时间,直到所需日期。
html:
<div flex-gt-xs>
<h4 class="md-title">Date From:</h4>
<md-datepicker ng-model="vm.sixMonthBeforeNow" md-placeholder="Date From:"></md-datepicker>
{{vm.sixMonthBeforeNow}}
</div>
控制器:
vm.sixMonthBeforeNow = new Date((+new Date) - 15778800000); // today - 6 month in ISO format (native for Angular Material Datepicker)
结果:
也许对某人有用...