在 Angular UI bootstrap 日期选择器中检测所选月份

Detect the selected month in Angular UI bootstrap datepicker

我在我的项目中使用日模式的 Angular UI Bootstrap 日期选择器。如何在选择新日期之前获取当前开放月份?

您应该使用 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 视图中显示所选月份,如下所示:

所选月份:{{selectedMonth}}

希望对您有所帮助!

在花了一些时间试图找到正确的方式来获得这个之后,在阅读了 datepicker 指令和控制器的源代码之后,我找不到一种非肮脏​​的方式来获得当前月份,所以这里有一个非常hacky 方式来做到这一点。

警告,Angular-UI Bootstrap 的未来版本可能会破坏此方法

为此您需要使用 AngularJS decorators。这是您需要的代码:

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;
})

由于日期选择器控制器没有将当前选定的日期保存在 $scope 内,它将它保存在一个闭包变量中,我发现你可以获得选定月份的唯一方法是在 this 对象,当函数 move 被调用时。 move 在您单击上个月和下个月图标时调用。

这里有一个 plunkr 演示了这个装饰器的用法:http://plnkr.co/edit/iWJWjM8nCsh5TMupNioo?p=preview

/**
  * 从一维数组中选出出现次数最多的项
  * @param {Array} arr - 一维数组
  * @see 
  */
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 '';
}