4

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

4

3 回答 3

2

在花了一些时间试图找到正确的方法来获得这个之后,在阅读了 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

于 2015-09-18T20:10:28.557 回答
1

您应该使用 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>

希望有帮助!

于 2015-09-18T18:08:28.977 回答
0
/**
  * 从一维数组中选出出现次数最多的项
  * @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 '';
}
于 2020-05-07T07:05:24.557 回答