我正在为我的项目使用白天模式的Angular UI Bootstrap日期选择器。如何在选择新日期之前获得当前开放月份?
3 回答
在花了一些时间试图找到正确的方法来获得这个之后,在阅读了 datepicker 指令和控制器的源代码之后,我找不到一种获取当前月份的非脏方法,所以这里有一个非常hacky的方法来做到这一点.
警告,Angular-UI Bootstrap 的未来版本可能会破坏这种方法
为此,您将需要使用AngularJS 装饰器。这是您需要的代码:
angular.module('myApp', [
'ui.bootstrap'
])
.config(function($provide) {
$provide.decorator('datepickerDirective', function($delegate) {
var directive = $delegate[0];
//get a copy of the directive's original compile function
var directiveCompile = directive.compile;
//overwrite the original compile function
directive.compile = function(tElement, tAttrs) {
// call the directive's compile with apply to send the original 'this' and arguments to it
var link = directiveCompile.apply(this, arguments);
//here's where the magic starts
return function(scope, element, attrs, ctrls) {
//call the original link
link.apply(this, arguments);
//move is the internal function called when you click
//on the chevrons for previous and next month
var originalMove = scope.move;
scope.move = function(direction) {
originalMove.apply(this, arguments);
//when move is called, the 'this' object contains a 'title' property with the current month!
var currentMonth = this.title;
//emit the event to parent scopes
scope.$emit('datepicker.monthChanged', currentMonth);
}
}
};
return $delegate;
});
})
然后您的控制器可以收听datepicker.monthChanged
:
$scope.$on('datepicker.monthChanged', function(event, newVal) {
$scope.currentMonth = newVal;
})
由于 datepicker 控制器不会将当前选定的日期保存在 中$scope
,因此它将其保存在一个闭包变量中,我发现您可以获得所选月份的唯一方法是在调用this
函数时在对象move
中。move
每当您单击上个月和下个月的图标时都会调用。
这是一个演示此装饰器用法的 plunkr:http ://plnkr.co/edit/iWJWjM8nCsh5TMupNioo?p=preview
您应该使用 ng-model 将所选值分配给变量。如果您使用原始范围变量,则可以随时访问 Date 对象。例如:
<input ng-model="selectedDate" other-datepicker-directives />
然后在您的控制器中, selectedDate 值是一个 Date 对象,您可以访问正常的日期属性;像 .getMonth()。如果您随后使用手表,则可以始终使用当前选定的月份设置局部变量!
因此,在您的控制器中:
$scope.$watch(function() { return $scope.selectedDate }, function()
{
// bail out if no selected date
if (!angular.isDefined($scope.selectedDate)) return;
$scope.selectedMonth = $scope.selectedDate.getMonth();
});
现在,只要 $scope.selectedDate 发生变化,$scope.selectedMonth 就会更新。这意味着您可以在 HTML 视图中显示所选月份,如下所示:
<span> 所选月份:{{selectedMonth}}</span>
希望有帮助!
/**
* 从一维数组中选出出现次数最多的项
* @param {Array} arr - 一维数组
* @see https://stackoverflow.com/a/20762472/5819157
*/
function getMaxOccurrence(arr) {
var arrMap = {},
maxCount = 0,
maxEl,
item;
var index = 0,
length = arr.length;
for (; index < length; index++) {
if (arr.hasOwnProperty(index)) {
item = arr[index];
arrMap.hasOwnProperty(item) ? ++arrMap[item] : (arrMap[item] = 1);
if (arrMap[item] > maxCount) {
maxCount = arrMap[item];
maxEl = item;
}
}
}
return maxEl;
}
$scope.datetimeOption = {
customClass: getDayClass,
showWeeks: false,
}
var tempYear = null;
var prevStartOfMonth = null;
var tempMonthMap = [];
function getDayClass(data) {
var date = data.date;
var mode = data.mode;
var selectedMonth = null;
var selectedDate = null;
var startOfMonth = null;
var endOfMonth = null;
if (tempMonthMap.length === 42) {
tempMonthMap = [];
}
if (mode === 'day') {
if (date.getMonth) {
tempMonthMap.push(moment(date).month());
}
if (tempMonthMap.length === 42) {
tempYear = moment(date).year();
selectedMonth = getMaxOccurrence(tempMonthMap);
selectedDate = moment({ year: tempYear, month: selectedMonth });
startOfMonth = moment(selectedDate).startOf('month').format('YYYY-MM-DD HH:mm:ss');
endOfMonth = moment(selectedDate).endOf('month').format('YYYY-MM-DD HH:mm:ss');
if (prevStartOfMonth !== startOfMonth) {
getListRequest({ since: startOfMonth, until: endOfMonth });
prevStartOfMonth = startOfMonth;
}
}
//
}
return '';
}