javascriptdatecalendarmomentjs

Change date with button (prev-next) from calendar using only moment library


I want the date to change month when the prev and next buttons are clicked.

The following code is working, as you can see.

It just seems like dirty code to me.

document.getElementById('nextdate').addEventListener('click', function() {
  let dataactual = document.getElementById('bday-month').value;
  let year = Number(dataactual.split('-')[0]);
  let month = Number(dataactual.split('-')[1]);
  month = month + 1;
  if (month > 12) {
    year = year + 1;
    month = 1;
  }
  let monthtwodigit = _.padStart(month.toString(), 2, '0')
  document.getElementById('bday-month').value = `${year}-${monthtwodigit}`
})

document.getElementById('prevdate').addEventListener('click', function() {
  let dataactual = document.getElementById('bday-month').value;
  let year = Number(dataactual.split('-')[0]);
  let month = Number(dataactual.split('-')[1]);
  month = month - 1;
  if (month < 1) {
    year = year - 1;
    month = 12;
  }
  let monthtwodigit = _.padStart(month.toString(), 2, '0')
  document.getElementById('bday-month').value = `${year}-${monthtwodigit}`
})
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" crossorigin="anonymous" referrerpolicy="no-referrer"
/>
<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment@2.30.1/moment.min.js"></script>

<input id="bday-month" type="month" name="bday-month" value="2024-08" />

<i id="prevdate" class="fa-solid fa-arrow-left"></i>
<i id="nextdate" class="fa-solid fa-arrow-right"></i>


<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>

I saw that there is a library called moment that allows you to 'play' with dates using pure js.

ATTENTION: the date must be in 'YYYY-MM' format

This library is new to me.

I tried to use it using the code below, but I noticed that I always have to transform the month or year into a number using Number() to add it by 1 and then subsequently use padStart to have two digits on the month.

let year = moment(dataactual,"YYYY-MM").format("YYYY");
let month = Number(moment(dataactual,"YYYY-MM").format("MM"));

Can someone please help me and make me understand how to adapt my code with moment?


Solution

  • I would delegate and just use string/int manipulation plus a spread and a ternary.

    const dateField = document.getElementById('bday-month');
    document.getElementById('monthChange').addEventListener('click', (e) => { // delegate from a wrapper
      const tgt = e.target;
      if (!tgt.matches('i')) return; // not an "i"
      let [yyyy, mm] = dateField.value.split('-').map(str => +str); // get and convert to number
      mm += tgt.id === 'nextdate' ? 1 : -1; // add or subtract depending on clicked span
      if      (mm > 12) { mm =  1; yyyy += 1; } 
      else if (mm <= 0) { mm = 12; yyyy -= 1; }
    
      dateField.value = `${yyyy}-${String(mm).padStart(2,'0')}`;
    })
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css" integrity="sha512-Kc323vGBEqzTmouAECnVceyQqyqdsSiqLQISBL29aUW4U/M7pSPA/gEUZQqv1cwx4OnYxTxve5UMg5GT6L4JJg==" crossorigin="anonymous" referrerpolicy="no-referrer"
    />
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/moment@2.30.1/moment.min.js"></script>
    
    <input id="bday-month" type="month" name="bday-month" value="2024-08" />
    <span id="monthChange">
      <i id="prevdate" class="fa-solid fa-arrow-left"></i>
      <i id="nextdate" class="fa-solid fa-arrow-right"></i>
    </span>
    
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>