Search code examples
javascriptbootstrap-datepicker

Boostrap datepicker stuck after setStartDate when click on decade or century


i have issue with boostrap datepicker after setting a start date allowed to pick which is when start date allowed is in 07-11-2021, but if a goes to decade view i can't go back to year 2021 or 2022, when i saw in decade years 2020 that supose to show it back years in allowed that decade is being disabled.

It is because the setStartDate is at 2021, so in decade view mode the 2020 is being disabled and can't show allowed year in that decade.

2020 is disabled becouse setStartDate is at 2021

Here the example

let d = new Date('08/11/2021');
$('.datepicker').datepicker({
    todayBtn: "linked",
    clearBtn: true,
    format: 'd MM yyyy'
}).datepicker('setStartDate', d);
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css" rel="stylesheet"/>

<div class="form-group">
  <label for="input" class="form-control-label">Date</label>
  <div class="input-group">
    <input class="form-control datepicker" placeholder="d M yyyy" type="text" name="waktu_bayar" id="input" data-date-end-date="0d">
    <div class="input-group-append">
      <span class="input-group-text"><i
                                                            class="ni ni-calendar-grid-58 px-1"></i></span>
    </div>
  </div>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>


Solution

  • For serval hour i'm tyring to digs these bug, look for other people question and so on, and the i'm get an epiphany that i should do something when the datepicker table being show, and the rest add some javascript in that show event.

    First we can create a function that can return a value abaut what decade or century from a date, than do some DOM to enableing some decade or a some century.

    Even through this is bit messy hire and there but i got the result what i want.


    Here The code

    let d = new Date('08/11/2021');
    
    // extended function for datepicker
    const dateRanges = (date = new Date(), rule = 10, sum = 0) => Math.floor(date.getFullYear() / rule) * rule + sum;
    
    $('.datepicker').datepicker({
      todayBtn: "linked",
      clearBtn: true,
      language: 'id',
      format: 'd MM yyyy'
    }).change(function(e) {
      // submitControl(e.target);
    }).on('show', function(e) {
      let allowedPicker = [],
        untilPicker = undefined,
        year = undefined;
      if (e.viewMode == 3) {
        // Start From This(d) Decade
        allowedPicker = [dateRanges(d)];
        // Until This(default dateRanges) Decade
        untilPicker = dateRanges();
        year = 10;
      } else if (e.viewMode == 4) {
        // daterange second params set to 100 a century
        // Start From This(d) Century
        allowedPicker = [dateRanges(d, 100)];
        // Until This(now) Century
        untilPicker = dateRanges(new Date(), 100);
        year = 100;
      }
      if (allowedPicker.length > 0) {
        if (allowedPicker.find(element => element == untilPicker) == undefined) {
          allowedPicker.push(untilPicker)
        }
        if (allowedPicker.length > 1 && allowedPicker[1] - allowedPicker[0] > year) {
          let loop = 1;
          do {
            if (allowedPicker.find(element => element == (loop * year)) == undefined) {
              allowedPicker.push(allowedPicker[loop - 1] + year);
            }
            loop++;
          } while ((allowedPicker[1] - allowedPicker[0]) / year > loop);
          allowedPicker.sort();
        }
        allowedPicker.forEach(pickElement => {
          $('.datepicker.datepicker-dropdown table tbody td>span.disabled:contains(' + pickElement + ')').removeClass('disabled');
        });
      }
    }).datepicker('setStartDate', d);
    <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" />
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/css/bootstrap-datepicker.min.css" rel="stylesheet" />
    
    <div class="form-group">
      <label for="input" class="form-control-label">Date</label>
      <div class="input-group">
        <input class="form-control datepicker" placeholder="d M yyyy" type="text" name="waktu_bayar" id="input" data-date-end-date="0d">
        <div class="input-group-append">
          <span class="input-group-text"><i
                                                                class="ni ni-calendar-grid-58 px-1"></i></span>
        </div>
      </div>
    </div>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datepicker/1.9.0/js/bootstrap-datepicker.min.js"></script>