title: Date range picker directive with AngularJS
body: <p>I'm having problems with date range picker directive and custom and ranges, i have modified the original <a href="https://github.com/luisfarzati/ng-bs-daterangepicker" rel="nofollow">https://github.com/luisfarzati/ng-bs-daterangepicker</a> the directive to this:</p>
  
  <pre><code>(function (angular) {
  'use strict';
  
  angular.module('ngBootstrap', []).directive('input', function ($compile, $parse) {
      return {
          restrict: 'E',
          require: 'ngModel',
          link: function ($scope, $element, $attributes, ngModel) {
              if ($attributes.type !== 'daterange') return;
  
              var options = {};
              options.format = $attributes.format || 'YYYY-MM-DD';
              options.separator = $attributes.separator || ' - ';
              options.minDate = $attributes.minDate &amp;&amp; moment($attributes.minDate);
              options.maxDate = $attributes.maxDate &amp;&amp; moment($attributes.maxDate);
              options.dateLimit = $attributes.limit &amp;&amp; moment.duration.apply(this, $attributes.limit.split(' ').map(function (elem, index) { return index === 0 &amp;&amp; parseInt(elem, 10) || elem; }) );
              options.ranges = $attributes.ranges &amp;&amp; $parse($attributes.ranges)($scope);
  
              function format(date) {
                  return date.format(options.format);
              }
  
              function formatted(dates) {
                  return [format(dates.startDate), format(dates.endDate)].join(options.separator);
              }
  
              ngModel.$formatters.unshift(function (modelValue) {
                  if (!modelValue) return '';
                  return modelValue;
              });
  
              ngModel.$parsers.unshift(function (viewValue) {
                  return viewValue;
              });
  
              ngModel.$render = function () {
                  if (!ngModel.$viewValue || !ngModel.$viewValue.startDate) return;
                  $element.val(formatted(ngModel.$viewValue));
              };
  
              $scope.$watch($attributes.ngModel, function (modelValue) {
                  if (!modelValue || (!modelValue.startDate)) {
                      ngModel.$setViewValue({ startDate: moment().startOf('day'), endDate: moment().startOf('day') });
                      return;
                  }
                  $element.data('daterangepicker').startDate = modelValue.startDate;
                  $element.data('daterangepicker').endDate = modelValue.endDate;
                  $element.data('daterangepicker').updateView();
                  $element.data('daterangepicker').updateCalendars();
                  $element.data('daterangepicker').updateInputText();
              });
  
              $element.daterangepicker(options, function(start, end) {
                  $scope.$apply(function () {
                      ngModel.$setViewValue({ startDate: start, endDate: end });
                      ngModel.$render();
                  });
              });         
          }
      };
  });
  
  })(angular);
  </code></pre>
  
  <p>to allow declarations like:</p>
  
  <pre><code>&lt;date-range-picker ng-model="dateRange"
                     class="pull-right"
                     style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc"
                     min-date="{{minDate}}"
                     max-date="{{maxDate}}"
                     ranges="{'Last 7 Days': [moment().subtract('days', 6), moment()],
                              'Last Month': [moment().subtract('month', 1).startOf('month'), moment().subtract('month', 1).endOf('month')],
                              'Last 3 Months': [moment().subtract('month', 3).startOf('month'), moment().subtract('month', 1).endOf('month')]}"&gt;
      &lt;i class="fontello-icon-calendar-alt-1"&gt;&lt;/i&gt;
      &lt;span&gt;....&lt;/span&gt;
  
  
      &lt;b class="caret" style="margin-top: 8px"&gt;&lt;/b&gt;
  &lt;/date-range-picker&gt;
  </code></pre>
  
  <p>Selecting custom range with the 2 calendars work fine as the original directive but the problem comes up when selecting one of the predefined ranges. 
  Can anybody give me a help with this?.</p>
  
  <p>UPDATE:</p>
  
  <p><strong>I HAVE FIXED THE PROBLEM</strong>, it worked this way:</p>
  
  <pre><code>&lt;date-range-picker ng-model="dateRange"
                                 class="pull-right"
                                 style="background: #fff; cursor: pointer; padding: 5px 10px; border: 1px solid #ccc"
                                 ng-model="dateRange"
                                 ranges="dateRange.ranges"
                                 &gt;
                  &lt;i class="fontello-icon-calendar-alt-1"&gt;&lt;/i&gt;
                  &lt;span&gt;&lt;/span&gt;
                  &lt;b class="caret" style="margin-top: 8px"&gt;&lt;/b&gt;
  &lt;/date-range-picker&gt;
  </code></pre>
  
  <p>With this minimum changes on the directive:</p>
  
  <pre><code>((angular) -&gt;
    "use strict"
    angular.module("directives.daterangepicker", []).directive "dateRangePicker", ($compile, $parse) -&gt;
      restrict: "E"
      require: "ngModel"
      link: ($scope, $element, $attributes, ngModel) -&gt;
        format = (date) -&gt;
          date.format options.format
        formatted = (dates) -&gt;
          [format(dates.startDate), format(dates.endDate)].join options.separator
        options = {}
        options.format = $attributes.format or "MMM D, YYYY"
        options.separator = $attributes.separator or " - "
        options.opens = $attributes.opens or "left"
        options.minDate = $attributes.minDate and moment($attributes.minDate)
        options.maxDate = $attributes.maxDate and moment($attributes.maxDate)
        options.dateLimit = $attributes.limit and moment.duration.apply(this, $attributes.limit.split(" ").map((elem, index) -&gt;
          index is 0 and parseInt(elem, 10) or elem
        ))
        options.ranges = $attributes.ranges and $parse($attributes.ranges)($scope)
        ngModel.$formatters.unshift (modelValue) -&gt;
          return ""  unless modelValue
          modelValue
  
        ngModel.$parsers.unshift (viewValue) -&gt;
          viewValue
  
        ngModel.$render = -&gt;
          return  if not ngModel.$viewValue or not ngModel.$viewValue.startDate
          $element.find("span").html(formatted(ngModel.$viewValue))
  
        $scope.$watch $attributes.ngModel, (modelValue) -&gt;
          if not modelValue or (not modelValue.startDate)
            ngModel.$setViewValue
              startDate: moment().startOf("day")
              endDate: moment().startOf("day")
  
            return
          $element.data("daterangepicker").startDate = modelValue.startDate
          $element.data("daterangepicker").endDate = modelValue.endDate
          $element.data("daterangepicker").minDate = modelValue.minDate
          $element.data("daterangepicker").maxDate = modelValue.maxDate
          $element.data("daterangepicker").updateView()
          $element.data("daterangepicker").updateCalendars()
          #$element.data("daterangepicker").updateInputText()
  
        $element.daterangepicker options, (start, end) -&gt;
          alert "$apply#{moment(start).toDate()}"
          alert options.maxDate
          $scope.$apply -&gt;
            ngModel.$setViewValue
              startDate: start
              endDate: end
  
            ngModel.$render()
  
  
  
  ) angular
  </code></pre>