Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using bootstrap-daterangepicker in an Angular directive

I'm having troubles using bootstrap-daterangepicker in an Angular directive. It works fine when initially loading the page, but when switching pages/states (I'm using ui-router) and going back to a page with a daterangepicker the plugin doesn't work anymore.

It throws this error:

TypeError: $(...).daterangepicker is not a function

It seems like the plugin has removed itself when changing states. Anyone an idea how to fix this?

app.directive("daterangepicker", function() {
    return {
      restrict: "A",
      scope: false,
      link: function($scope, $element, $attr){

        $($element).daterangepicker({
          format: "DD.MM.YYYY",
          startDate: moment().subtract('days', 1),
          endDate: new Date(),          
          buttonClasses: ['btn-primary'],
        }, function(from, to) {
          $scope.date = {from: from, to: to};
          $scope.$apply(); // I need apply() here to use the two-way-databinding
        });
      }
    }
  });
like image 917
Tim Van Dijck Avatar asked Apr 07 '16 15:04

Tim Van Dijck


2 Answers

I would avoid reinventing the wheel, there is already a directive provided by several projects, use the https://angular-ui.github.io/bootstrap/

Import the module:

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

and the use it like that:

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

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

<body>

  <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="DatepickerPopupDemoCtrl">
    <pre>Selected date is: <em>{{dt | date:'fullDate' }}</em></pre>

    <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>
</body>

</html>

The controller:

angular.module('ui.bootstrap.demo', ['ngAnimate', 'ui.bootstrap']);
angular.module('ui.bootstrap.demo').controller('DatepickerPopupDemoCtrl', 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 '';
      }
    });

plunker: http://plnkr.co/edit/LZgUAZQkNKgDrUZAVWSa?p=preview

like image 104
thegio Avatar answered Oct 22 '22 06:10

thegio


I finally found the solution to my problem!

To be clear: the same bug was happening with the angular-daterangepicker plugin.

It was actually caused because some other dependency loaded an extra jQuery. Because of this multiple jQuerys were loaded and this caused the bug.

like image 22
Tim Van Dijck Avatar answered Oct 22 '22 07:10

Tim Van Dijck