Angular UI Datepicker 每月限制天数 [英] Angular UI Datepicker Limiting Days per month

查看:28
本文介绍了Angular UI Datepicker 每月限制天数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用角度日期选择器:

http://angular-ui.github.io/bootstrap/#/datepicker

目前硬编码为显示 42 天或 6 周.

我想知道如何在 ui-bootstrap-0.13.1.js 中覆盖(即 angular 装饰器)此功能以显示 4 周.

功能如下:

ctrl._refreshView = function() {var year = ctrl.activeDate.getFullYear(),月 = ctrl.activeDate.getMonth(),firstDayOfMonth = 新日期(年,月,1),差异 = ctrl.startingDay - firstDayOfMonth.getDay(),numDisplayedFromPreviousMonth = (difference > 0) ?7 - 差异:-差异,firstDate = 新日期(firstDayOfMonth);如果(numDisplayedFromPreviousMonth > 0){firstDate.setDate(-numDisplayedFromPreviousMonth + 1);}//42 是六个月日历上的天数var days = getDates(firstDate, 42);for (var i = 0; i <42; i++) {天[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), {次要: days[i].getMonth() !== 月,uid:scope.uniqueId + '-' + i});}scope.labels = new Array(7);for (var j = 0; j <7; j++) {范围.标签[j] = {abbr: dateFilter(days[j].date, ctrl.formatDayHeader),完整:日期过滤器(天[j].日期,'EEEE')};}scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle);scope.rows = ctrl.split(days, 7);如果(范围.showWeeks){scope.weekNumbers = [];var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7,numWeeks = scope.rows.length;for (var curWeek = 0; curWeek 

我已尝试将 42 天硬编码为更小,但它破坏了日历计算.只是看看以前是否有人扩展过这个?

干杯

解决方案

如果您使用装饰器,您应该能够将 _refreshView 包裹在一个新的编译函数中,该函数包裹着旧的链接函数.在您的 ctrl._refreshView 包装器中,您可以执行以下操作:

directive.compile = function() {返回函数(范围,元素,属性,ctrl){link.apply(this, arguments);var _refreshView = ctrl._refreshView;ctrl._refreshView = function() {_refreshView.apply(this, arguments);removeAnySecondaryOnlyRows(scope.rows);};removeAnySecondaryOnlyRows(scope.rows);};};

还有:

//删除任何只包含次要"日期的行(其他月份的)函数 removeAnySecondaryOnlyRows(rows) {for (var i = 0; i < rows.length; i++) {var row = rows[i],areAllSecondary = false;//检查第一个和最后一个单元格的 .secondary 属性areAllSecondary = row[0].secondary &&row[(row.length - 1)].secondary;如果(areAllSecondary){row.splice(i, 1);一世 - ;}}}

一起作为一个功能片段,包括一个自定义模板和一些 css 来隐藏次要"天(来自不同月份的那些天):

(function() {严格使用";angular.module('myApp', ['ui.bootstrap']).config(['$provide', 装饰]).controller("MainController", ['$scope', MainController]);功能装饰($提供){//修复日期选择器日模式"以仅显示从当月开始的天数的行$provide.decorator('daypickerDirective', ['$delegate', daypickerDirectiveDecorator]);功能 daypickerDirectiveDecorator($delegate) {var 指令 = $delegate[0],链接 = 指令.链接;//自定义 html 模板:directive.templateUrl = "common/directives/uiBootstrapDatepickerDay.tpl.html";指令.编译 = 函数(){返回函数(范围,元素,属性,ctrl){link.apply(this, arguments);var _refreshView = ctrl._refreshView;ctrl._refreshView = function() {_refreshView.apply(this, arguments);removeAnySecondaryOnlyRows(scope.rows);};removeAnySecondaryOnlyRows(scope.rows);};};返回 $delegate;}//删除任何只包含次要"日期的行(其他月份的)函数 removeAnySecondaryOnlyRows(rows) {for (var i = 0; i < rows.length; i++) {var row = rows[i],areAllSecondary = false;//检查第一个和最后一个单元格的 .secondary 属性areAllSecondary = row[0].secondary &&row[(row.length - 1)].secondary;如果(areAllSecondary){rows.splice(i, 1);一世 - ;}}}}函数 MainController($scope) {$scope.dt = new Date();}})();

/*从其他月份隐藏天数的示例:我们在加载 datepicker 指令的元素上放置了一个datepicker"类,并且我们已经自定义了一天模板,如果这是一个次要"日(另一个月的一天).*/.datepicker .invis {可见性:隐藏;}

<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="样式表"><script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script><script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.min.js"></script><div ng-app="myApp" ng-controller="MainController"><!--修改日模板以将invis"类添加到次日按钮.这可以/应该保存在一个单独的文件中 (http://stackoverflow.com/a/26339919/446030)--><script id="common/directives/uiBootstrapDatepickerDay.tpl.html" type="text/ng-template"><table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}"><头><tr><th><button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-人字形左"></i></th><th colspan="{{5 + showWeeks}}"><button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong></th><th><button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-右"></i></th></tr><tr><th ng-if="showWeeks" class="text-center"></th><th ng-repeat="label in labels track by $index" class="text-center"><small aria-label="{{label.full}}">{{label.abbr}}</小></th></tr></thead><tr ng-repeat="row in rows track by $index"><td ng-if="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em></td><td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" ng-class="dt.customClass"><!--######## 'invis' 类添加到按钮上的 ng-class 中:#######--><button type="button" style="min-width:100%;"class="btn btn-default btn-sm" ng-class="{'btn-info': dt.selected, active: isActive(dt), 'invis': dt.secondary}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{'text-muted': dt.secondary, 'text-info': dt.current}">{{dt.label}}</span></td></tr></tbody><div><strong>所选日期:</strong>{{dt.toDateString()}}

<div style="display:inline-block; min-height:290px;"><div datepicker ng-model="dt" class="well well-sm datepicker"></div>

I am using using the angular datepicker:

http://angular-ui.github.io/bootstrap/#/datepicker

Currently it is hardcoded to display 42 days or 6 weeks.

I would like to know how to overwrite (ie. angular decorator) this function in ui-bootstrap-0.13.1.js to display 4 weeks.

Here is the function:

ctrl._refreshView = function() {
  var year = ctrl.activeDate.getFullYear(),
    month = ctrl.activeDate.getMonth(),
    firstDayOfMonth = new Date(year, month, 1),
    difference = ctrl.startingDay - firstDayOfMonth.getDay(),
    numDisplayedFromPreviousMonth = (difference > 0) ? 7 - difference : -difference,
    firstDate = new Date(firstDayOfMonth);

  if (numDisplayedFromPreviousMonth > 0) {
    firstDate.setDate(-numDisplayedFromPreviousMonth + 1);
  }

  // 42 is the number of days on a six-month calendar
  var days = getDates(firstDate, 42);
  for (var i = 0; i < 42; i++) {
    days[i] = angular.extend(ctrl.createDateObject(days[i], ctrl.formatDay), {
      secondary: days[i].getMonth() !== month,
      uid: scope.uniqueId + '-' + i
    });
  }

  scope.labels = new Array(7);
  for (var j = 0; j < 7; j++) {
    scope.labels[j] = {
      abbr: dateFilter(days[j].date, ctrl.formatDayHeader),
      full: dateFilter(days[j].date, 'EEEE')
    };
  }

  scope.title = dateFilter(ctrl.activeDate, ctrl.formatDayTitle);
  scope.rows = ctrl.split(days, 7);

  if (scope.showWeeks) {
    scope.weekNumbers = [];
    var thursdayIndex = (4 + 7 - ctrl.startingDay) % 7,
      numWeeks = scope.rows.length;
    for (var curWeek = 0; curWeek < numWeeks; curWeek++) {
      scope.weekNumbers.push(
        getISO8601WeekNumber(scope.rows[curWeek][thursdayIndex].date));
    }
  }
};

I've tried hard coding the 42 days to something smaller but it breaks the calender calculation. Just looking if anyone has extended this before?

Cheers

解决方案

You should be able to wrap _refreshView within a new compile function wrapping the old link function, if you use decorator. Within your ctrl._refreshView wrapper, you can do something like:

directive.compile = function() {
  return function(scope, element, attrs, ctrl) {
    link.apply(this, arguments);

    var _refreshView = ctrl._refreshView;
    ctrl._refreshView = function() {
      _refreshView.apply(this, arguments);
      removeAnySecondaryOnlyRows(scope.rows);
    };

    removeAnySecondaryOnlyRows(scope.rows);
  };
};

And:

//Remove any rows that contain only 'secondary' dates (those from other months)
function removeAnySecondaryOnlyRows(rows) {
  for (var i = 0; i < rows.length; i++) {
    var row = rows[i],
      areAllSecondary = false;

    //check the first and the last cell's .secondary property
    areAllSecondary = row[0].secondary && row[(row.length - 1)].secondary;

    if (areAllSecondary) {
      rows.splice(i, 1);
      i--;
    }
  }
}

And all together as a functioning snippet, including a custom template and some css to hide the 'secondary' days (those from a different month):

(function() {
  "use strict";

  angular.module('myApp', ['ui.bootstrap'])
    .config(['$provide', Decorate])
    .controller("MainController", ['$scope', MainController]);

  function Decorate($provide) {

    //fix for Datepicker 'day mode' to show only rows with days from the current month
    $provide.decorator('daypickerDirective', ['$delegate', daypickerDirectiveDecorator]);

    function daypickerDirectiveDecorator($delegate) {
      var directive = $delegate[0],
        link = directive.link;

      // custom html template:
      directive.templateUrl = "common/directives/uiBootstrapDatepickerDay.tpl.html";

      directive.compile = function() {
        return function(scope, element, attrs, ctrl) {
          link.apply(this, arguments);

          var _refreshView = ctrl._refreshView;
          ctrl._refreshView = function() {
            _refreshView.apply(this, arguments);
            removeAnySecondaryOnlyRows(scope.rows);
          };

          removeAnySecondaryOnlyRows(scope.rows);
        };
      };

      return $delegate;
    }

    //Remove any rows that contain only 'secondary' dates (those from other months)
    function removeAnySecondaryOnlyRows(rows) {
      for (var i = 0; i < rows.length; i++) {
        var row = rows[i],
          areAllSecondary = false;

        //check the first and the last cell's .secondary property
        areAllSecondary = row[0].secondary && row[(row.length - 1)].secondary;

        if (areAllSecondary) {
          rows.splice(i, 1);
          i--;
        }
      }
    }
  }

  function MainController($scope) {
    $scope.dt = new Date();
  }
})();

/*
Example of hiding days from other months:
We've put a class of 'datepicker' on the element loading the datepicker directive,
and we've customised the day template to add an 'invis' class to the day's button if
it's a 'secondary' day (a day from another month).
*/

.datepicker .invis {
  visibility: hidden;
}

<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.28/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/0.13.0/ui-bootstrap-tpls.min.js"></script>

<div ng-app="myApp" ng-controller="MainController">

  <!--
   Modified day template to add an 'invis' class to secondary day buttons.
   This could/should be kept in a separate file (http://stackoverflow.com/a/26339919/446030)
   -->
  <script id="common/directives/uiBootstrapDatepickerDay.tpl.html" type="text/ng-template">
    <table role="grid" aria-labelledby="{{uniqueId}}-title" aria-activedescendant="{{activeDateId}}">
      <thead>
        <tr>
          <th>
            <button type="button" class="btn btn-default btn-sm pull-left" ng-click="move(-1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-left"></i>
            </button>
          </th>
          <th colspan="{{5 + showWeeks}}">
            <button id="{{uniqueId}}-title" role="heading" aria-live="assertive" aria-atomic="true" type="button" class="btn btn-default btn-sm" ng-click="toggleMode()" ng-disabled="datepickerMode === maxMode" tabindex="-1" style="width:100%;"><strong>{{title}}</strong>
            </button>
          </th>
          <th>
            <button type="button" class="btn btn-default btn-sm pull-right" ng-click="move(1)" tabindex="-1"><i class="glyphicon glyphicon-chevron-right"></i>
            </button>
          </th>
        </tr>
        <tr>
          <th ng-if="showWeeks" class="text-center"></th>
          <th ng-repeat="label in labels track by $index" class="text-center"><small aria-label="{{label.full}}">{{label.abbr}}</small>
          </th>
        </tr>
      </thead>
      <tbody>
        <tr ng-repeat="row in rows track by $index">
          <td ng-if="showWeeks" class="text-center h6"><em>{{ weekNumbers[$index] }}</em>
          </td>
          <td ng-repeat="dt in row track by dt.date" class="text-center" role="gridcell" id="{{dt.uid}}" ng-class="dt.customClass">
            <!--######## 'invis' class added in ng-class on the button: #######-->
            <button type="button" style="min-width:100%;" class="btn btn-default btn-sm" ng-class="{'btn-info': dt.selected, active: isActive(dt), 'invis': dt.secondary}" ng-click="select(dt.date)" ng-disabled="dt.disabled" tabindex="-1"><span ng-class="{'text-muted': dt.secondary, 'text-info': dt.current}">{{dt.label}}</span>
            </button>
          </td>
        </tr>
      </tbody>
    </table>
  </script>

  <div>
    <strong>Selected date:</strong> {{dt.toDateString()}}
  </div>
  <div style="display:inline-block; min-height:290px;">
    <div datepicker ng-model="dt" class="well well-sm datepicker"></div>
  </div>

</div>

这篇关于Angular UI Datepicker 每月限制天数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆