将保存时间戳的 ng-model 绑定到 datetime-local 输入
Bind ng-model holding a timestamp to datetime-local input
我正在尝试使用 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
必须是日期对象:
$scope.object = {
name: 'Demo',
value: new Date(1433109600000)
}
或者创建一个指令:
app.directive('bindTimestamp', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
ngModel.$formatters.push(function (value) {
return new Date(value);
});
}
};
});
完成@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;
});
};
}
}
};
});
茉莉花测试:
描述('bindTimestamp : timestamps',函数(){
// 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);
});
});
我正在尝试使用 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
必须是日期对象:
$scope.object = {
name: 'Demo',
value: new Date(1433109600000)
}
或者创建一个指令:
app.directive('bindTimestamp', function () {
return {
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attrs, ngModel) {
ngModel.$formatters.push(function (value) {
return new Date(value);
});
}
};
});
完成@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;
});
};
}
}
};
});
茉莉花测试: 描述('bindTimestamp : timestamps',函数(){
// 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);
});
});