30개의 프로젝트로 배우는 프론트엔드 with VanillaJS (3-3) date picker

productuidev·2022년 9월 15일
0

FE Study

목록 보기
54/67
post-thumbnail
post-custom-banner

[fastcampus] 30개의 프로젝트로 배우는 프론트엔드 with VanillaJS (3-3)

(3) 바닐라 자바스크립트로 만드는 date picker

jQuery 라이브러리를 사용하지 않고 만드는 date picker

날짜 조회 기능 : 이전 달/다음 달 선택

  • 캘린더 상단의 < (이전) > (다음) 달 버튼 선택 시 이전 달/다음 달로 캘린더를 갱신하는 기능
  • 1월 ~ 12월 : 0 ~ 11
  • 1씩 증가/감소를 통해 연/월/일 갱신

src/js/index.js

class DatePicker {

  addEvent() {
  
    // 다음 달/이전 달 이동 버튼
    this.nextBtnEl.addEventListener('click', this.moveToNextMonth.bind(this));
    this.prevBtnEl.addEventListener('click', this.moveToPrevMonth.bind(this));
  }

  // 캘린더 다음 달 이동 버튼
  moveToNextMonth() {
    this.#calendarDate.month++; // +1 증가
    // 조건 1월이 되면 (0~11)
    // 다음해로 -1, 다시 12월 (11) 으로
    if (this.#calendarDate.month > 11) {
      this.#calendarDate.month = 0;
      this.#calendarDate.year++;
    }
    this.updateMonth(); // 월 갱신
    this.updateDates(); // 일 갱신
  }

  // 캘린더 이전 달 이동 버튼
  moveToPrevMonth() {
    this.#calendarDate.month--; // -1 감소
    // 조건 12월이 되면 (0~11)
    // 다음해로 +1, 다시 1월 (0) 으로
    if (this.#calendarDate.month < 0) {
      this.#calendarDate.month = 11;
      this.#calendarDate.year--;
    }
    this.updateMonth(); // 월 갱신
    this.updateDates(); // 일 갱신
  }
  
}

날짜 입력 기능 : 선택한 날짜 정보로 input 변경

public/index.html

    <div class="date-picker" id="date-picker">
      <!-- ! date-input 동적으로 생성으로 생성할 것이므로 안에 임의의 날짜는 삭제 -->
      <div class="date-input" id="date-input">2022/01/15</div>
      <div class="calendar" id="calendar">
        <div class="month" id="month">
          <div class="arrows" id="prev">&lt;</div>
          <div class="mth" id="content"></div>
          <div class="arrows" id="next">&gt;</div>
        </div>
        <div class="days" id="days">
          <div class="day">SUN</div>
          <div class="day">MON</div>
          <div class="day">TUE</div>
          <div class="day">WED</div>
          <div class="day">THU</div>
          <div class="day">FRI</div>
          <div class="day">SAT</div>
        </div>
        <div class="dates" id="dates"></div>
      </div>
    </div>

src/js/index.js

초기 input 설정 및 초기 선택 날짜 (날짜 형식 및 data-value)
setDateInput 함수

  constructor() {
    this.initSelectedDate();
    this.setDateInput();
  }
  
  initSelectedDate() {
    this.selectedDate = { ...this.#calendarDate };
  }

  setDateInput() {
    this.dateInputEl.textContent = this.formateDate(this.selectedDate.data);
    this.dateInputEl.dataset.value = this.selectedDate.data;
  }

input을 눌렀을 때 선택 날짜 입력

  addEvent() {
    this.calendarDatesEl.addEventListener(
      'click',
      this.onClickSelectDate.bind(this),
    );
  }

data-date 속성 활용하여 input 선택 날짜 입력 (이벤트 버블링)

  onClickSelectDate() {
    const eventTarget = event.target;
    if (eventTarget.dataset.date) {
      this.calendarDatesEl
        .querySelector('.selected')
        ?.classList.remove('selected'); // 없을수도 있으므로 ?
      eventTarget.classList.add('selected');

      // 선택한 날짜
      this.selectedDate = {
        data: new Date(
          this.#calendarDate.year,
          this.#calendarDate.month,
          eventTarget.dataset.date,
        ),
        year: this.#calendarDate.year,
        month: this.#calendarDate.month,
        date: eventTarget.dataset.date,
      };

      // 날짜 형식 및 data-value
      this.setDateInput();

      // 캘린더 선택 시 제거
      this.calendarEl.classList.remove('active');
    }
  }

input에 출력되는 날짜 형식(포맷) 출력 (YYYY-MM-DD)

src/js/index.js

  formateDate(dateData) {
    let date = dateData.getDate();
    if (date < 10) {
      date = `0${date}`;
    }

    let month = dateData.getMonth() + 1;
    if (month < 10) {
      month = `0${month}`;
    }

    let year = dateData.getFullYear();
    return `${year}/${month}/${date}`;
  }

선택된 날짜의 배경색상 표시 (data-date 속성 찾아서)
선택된 해/달과 비교

src/scss/style.scss

    .dates {
        &.today {
          background-color: #ca92ff;
        }

        &.selected {
          background-color: #00ca85;
        }
      }

src/js/index.js

updateDates() {
    this.markSelectedDate(); // 선택된 날짜를 마크하는 메소드
  }

  markSelectedDate() {
    if (
      this.selectedDate.year === this.#calendarDate.year &&
      this.selectedDate.month === this.#calendarDate.month
    ) {
      this.calendarDatesEl
        .querySelector(`[data-date='${this.selectedDate.date}']`)
        .classList.add('selected');
    }
  }

캘린더를 토글(펼침/닫힘) 시 보고 있는 날짜를 선택된 날짜 기반으로 보도록 (다시 토글 시)

src/js/index.js

  toggleCalendar() {
    if (this.calendarEl.classList.contains('active')) {
      this.#calendarDate = { ...this.selectedDate };
    }
    this.calendarEl.classList.toggle('active');
    this.updateMonth();
    this.updateDates();
  }

결과


🙅🏻‍♀️JSX🙅🏻‍♂️ 하는 날이 올런지..🧑🏻‍💻🗣

profile
필요한 내용을 공부하고 저장합니다.
post-custom-banner

0개의 댓글