0
votes

I am using angular bootstrap datetimepicker. I want to make $dates.selectable = false for past date and time.

How can I do that?

Please let me know if you need the code example.

4

4 Answers

1
votes

I assume you are using the angular-bootstrap-datetimepicker, so you will want to use the before-render callback.

The code would look something like this:

function BeforeRender ($dates) {
  var activeDate = moment();

  $dates.filter(function (date) {
    return date.localDateValue() >= activeDate.valueOf()
  }).forEach(function (date) {
    date.selectable = false;
  })
}

The Read Me has an example of a date range picker that does what you want.

0
votes

As you can see on its website (https://angular-ui.github.io/bootstrap/#/datepicker) you can pass through your configuration object a "dateDisabled".

This is the html of the example:

<style>
  .full button span {
    background-color: limegreen;
    border-radius: 32px;
    color: black;
  }
  .partially button span {
    background-color: orange;
    border-radius: 32px;
    color: black;
  }
</style>
<div ng-controller="DatepickerDemoCtrl">
    <pre>Selected date is: <em>{{dt | date:'fullDate' }}</em></pre>

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

    <h4>Popup</h4>
    <div class="row">
      <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="dt" is-open="popup1.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" alt-input-formats="altInputFormats" />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open1()"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
      </div>

      <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" uib-datepicker-popup ng-model="dt" is-open="popup2.opened" datepicker-options="dateOptions" ng-required="true" close-text="Close" />
          <span class="input-group-btn">
            <button type="button" class="btn btn-default" ng-click="open2()"><i class="glyphicon glyphicon-calendar"></i></button>
          </span>
        </p>
      </div>
    </div>
    <div class="row">
      <div class="col-md-6">
        <label>Format: <span class="muted-text">(manual alternate <em>{{altInputFormats[0]}}</em>)</span></label> <select class="form-control" ng-model="format" ng-options="f for f in formats"><option></option></select>
      </div>
    </div>

    <hr />
    <button type="button" class="btn btn-sm btn-info" ng-click="today()">Today</button>
    <button type="button" class="btn btn-sm btn-default" ng-click="setDate(2009, 7, 24)">2009-08-24</button>
    <button type="button" class="btn btn-sm btn-danger" ng-click="clear()">Clear</button>
    <button type="button" class="btn btn-sm btn-default" ng-click="toggleMin()" uib-tooltip="After today restriction">Min date</button>
</div>

And this is the JavaScript:

angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function ($scope) {
  $scope.today = function() {
    $scope.dt = new Date();
  };
  $scope.today();

  $scope.clear = function() {
    $scope.dt = null;
  };

  $scope.inlineOptions = {
    customClass: getDayClass,
    minDate: new Date(),
    showWeeks: true
  };

  $scope.dateOptions = {
    dateDisabled: disabled,
    formatYear: 'yy',
    maxDate: new Date(2020, 5, 22),
    minDate: new Date(),
    startingDay: 1
  };

  // Disable weekend selection
  function disabled(data) {
    var date = data.date,
      mode = data.mode;
    return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
  }

  $scope.toggleMin = function() {
    $scope.inlineOptions.minDate = $scope.inlineOptions.minDate ? null : new Date();
    $scope.dateOptions.minDate = $scope.inlineOptions.minDate;
  };

  $scope.toggleMin();

  $scope.open1 = function() {
    $scope.popup1.opened = true;
  };

  $scope.open2 = function() {
    $scope.popup2.opened = true;
  };

  $scope.setDate = function(year, month, day) {
    $scope.dt = new Date(year, month, day);
  };

  $scope.formats = ['dd-MMMM-yyyy', 'yyyy/MM/dd', 'dd.MM.yyyy', 'shortDate'];
  $scope.format = $scope.formats[0];
  $scope.altInputFormats = ['M!/d!/yyyy'];

  $scope.popup1 = {
    opened: false
  };

  $scope.popup2 = {
    opened: false
  };

  var tomorrow = new Date();
  tomorrow.setDate(tomorrow.getDate() + 1);
  var afterTomorrow = new Date();
  afterTomorrow.setDate(tomorrow.getDate() + 1);
  $scope.events = [
    {
      date: tomorrow,
      status: 'full'
    },
    {
      date: afterTomorrow,
      status: 'partially'
    }
  ];

  function getDayClass(data) {
    var date = data.date,
      mode = data.mode;
    if (mode === 'day') {
      var dayToCheck = new Date(date).setHours(0,0,0,0);

      for (var i = 0; i < $scope.events.length; i++) {
        var currentDay = new Date($scope.events[i].date).setHours(0,0,0,0);

        if (dayToCheck === currentDay) {
          return $scope.events[i].status;
        }
      }
    }

    return '';
  }
});

Pay attention on this row:

dateDisabled: disabled,

By passing this in your configuration object you set a function disabled as a handler for disabling the dates. So after a few lines you can read the disabled function:

// Disable weekend selection
function disabled(data) {
  var date = data.date,
  mode = data.mode;
  return mode === 'day' && (date.getDay() === 0 || date.getDay() === 6);
}

The two parameters of the function are:

  • date
  • mode

date is a normal JavaScript date object and you can use all the date methods for this.

mode is the date mode, as you can see in this example you verify if mode is equal to "day".

So in this way you can simply disable a range of dates or custom days.

0
votes

You can try to insert

startDate:"-0m",

this code disable all the dates in the past that becomes non clickables.

0
votes

I was facing this issue recently, and after reading some stackoverflow answers, I came up with this code :

This takes care of day, hour and minute also.

    $scope.startDateBeforeRender = function($view, $dates, $leftDate, $upDate, $rightDate) {
        const minDate = moment().local().startOf($view).valueOf();
        for(let i=0; i < $dates.length; i++) {
            if($view === 'day' || $view === 'hour') {
                if (minDate > $dates[i].localDateValue()) {
                    $dates[i].selectable = false;
                }
            } else {
                if (minDate >= $dates[i].localDateValue()) {
                    $dates[i].selectable = false;
                }
            }
        }
    };

Html as :

<md-input-container class="md-block" flex-gt-sm>
    <label>Time</label>
    <div class="dropdown">
        <a class="dropdown-toggle" id="dropdown2" role="button" data-toggle="dropdown" data-target="#" href="javascript:void(0);">
            <div class="input-group">
                <input type="text" class="form-control" data-ng-model="data.dateDropDownInput"><span class="input-group-addon"><i class="glyphicon glyphicon-calendar"></i></span>
            </div>
        </a>
        <ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
            <datetimepicker data-ng-model="data.dateDropDownInput" data-before-render="startDateBeforeRender($view, $dates, $leftDate, $upDate, $rightDate)" data-datetimepicker-config="{ dropdownSelector: '#dropdown2' }"/>
        </ul>
    </div>
</md-input-container>