Search code examples
javascriptangularjsangular-ui-bootstraptimepickerbootstrap-datetimepicker

How to Increase Date after the time in Timepicker passes midnight?


I have a startDate model which I have bound to a bootstrap date picker and timepicker. When I increase the time in the Time picker and it passes midnight, I need to have the model increase its date as well. Following is my existing code.

angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);

angular.module('ui.bootstrap.demo').controller('DatepickerDemoCtrl', function($scope) {

  $scope.hstep = 1;
  $scope.mstep = 15;

  $scope.ismeridian = true;
  $scope.toggleMode = function() {
    $scope.ismeridian = !$scope.ismeridian;
  };

  $scope.today = function() {
    $scope.startDate = new Date();
  };

  $scope.startDateState = {
    opened: false
  }; /* Model to keep track if Popup is open */

  $scope.today(); /* Sets Date as Today Initially */
  $scope.showWeeks = false; /* Hides Week Numbers */
  $scope.minDate = new Date(); /* Disables past dates */
  $scope.format = 'dd MMM, yyyy'; /* Date Format Setting */
  $scope.dateOptions = {
    startingDay: 1,
    showWeeks: false,
  }; /* to be passed in the date-options directive */

  $scope.open = function() {
    $scope.startDateState.opened = true;
  }; /* Button Click Event to open Popup */

});
<!doctype html>
<html ng-app="ui.bootstrap.demo">

<head>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
  <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.js"></script>
  <script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.3.js"></script>
  <script src="example.js"></script>
  <link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
</head>

<body>

  <div ng-controller="DatepickerDemoCtrl">
    <pre>Start date is: <em>{{startDate| date:"MM/dd/yyyy 'at' h:mma"}}</em></pre>
    <div class="row">
      <div class="col-md-6">
        <p class="input-group">
          <input type="text" class="form-control" uib-datepicker-popup="{{format}}" ng-model="startDate" is-open="startDateState.opened" on-open-focus="false" min-date="minDate" show-button-bar="false" datepicker-options="dateOptions" ng-required="true" />
          <span class="input-group-btn">
                <button type="button" class="btn btn-default" ng-click="open()"><i class="glyphicon glyphicon-calendar"></i></button>
              </span>
        </p>
        <uib-timepicker ng-model="startDate" hour-step="hstep" minute-step="mstep" show-meridian="ismeridian"></uib-timepicker>
      </div>
    </div>
  </div>
</body>

</html>

How to approach this problem?


Solution

  • Akash,

    The way I approached the problem was to use the ng-change directive on the date input field.

    HTML

    <input ... ng-change="startDateChanged({{startDateTime}})"></input>
    

    You will notice that the parameter being passed to the controllers scope function is a literal expression. The reason for this is so that we can compare what the original value of the ng-model date object was before it was modified by the up or down arrows from the time picker.

    Controller

    var app = angular.module('plunker', ['ui.bootstrap']);
    
    app.controller('MainCtrl', function($scope) {
      var twelveAm = 0;
      var oneAm = 1;
      var elevenPm = 23;
      $scope.hStep = 1;
      $scope.mStep = 15;
      $scope.startDateTime = new Date();
      $scope.today = new Date();
    
      $scope.datePickerState = {
        startDateOpened: false
      };
    
      $scope.datePickerOptions = {
        "show-weeks": false
      };
    
      $scope.open = () => {
        $scope.datePickerState.startDateOpened = true;
      };
    
      $scope.startDateChanged = (originalModel) => {
        var nd = _.clone($scope.startDateTime);
        var od = new Date(originalModel);
    
        if (nd.getHours() === twelveAm) {
          if (od.getHours() === elevenPm) {
            nd.setDate(nd.getDate() + 1);
            $scope.startDateTime = nd;
          } else if (od.getHours() === oneAm) {
            nd.setDate(nd.getDate() - 1);
            $scope.startDateTime = nd;
          }
        }
      };
    });
    

    Inside the method $scope.startDateChanged(), I first create two new date objects, one holding the value of the original datetime (the expression that was passed in) and another with the new datetime. Then I check to see if the new datetime (nd) has a value of 12 AM. If it does, I then check to see if the original datetime (od) has a value of 11 PM or 1 AM and act accordingly (if its 11 PM, it means the button we pushed was to increase the time and therefore the day, otherwise, we are lowering the time and henceforth the day)

    I've included a Plunker to illustrate the example.

    https://plnkr.co/edit/dDMfpXmy3JBEjXzOca9v