ABOUT ME

-

  • [ Vue ] VCalendar 단일(single), 기간(range), 다중(multi), date-picker 구현
    Front/Vue 2025. 8. 5. 01:20
    반응형

    date-picker를 찾다보면 대부분의 date-picker가 dropdown형식으로 되어서 vcalendar로 달력으로 바로 날짜를 선택할 수 있도록 기능을 구현

     

    VCalendar를 사용하면서 css 작업이 생각보다 다른 라이브러리보다 좀 건드리기가 복잡했기에

    혹시 css설정 관련해서 필요한것이 있으면 알려드리겠습니다.


    Installment

    vcalendar docs를 보며 진행

    https://vcalendar.io/getting-started/installation.html

     

    vcalendar를 사용하기 위해 라이브러리를 설치

    npm install v-calendar@next @popperjs/core

     

    전역으로 VCalendar를 전역으로 사용하기위해 main에서 전역으로 VCalendar 플러그인을 등록

    import { setupCalendar, Calendar, DatePicker } from 'v-calendar';
    import 'v-calendar/style.css';
    
    // Use plugin defaults (optional)
    app.use(setupCalendar, {})
    
    // Use the components
    app.component('VCalendar', Calendar)
    app.component('VDatePicker', DatePicker)

     


    Single

    calendar에서 단일 날짜 선택 기능을 구현

    단일은 VDatePicker를 이용하고 v-model로 바인딩해주면 간단하게 구현이 가능하다

    <script>
    	const selectedDate = ref(null)
    </script>
    <template>
    	<VDatePicker v-model="selectedDate" mode="date" />
    </template>


    Range

    기간 선택의 경우에는 변수를 start와 end 객체로 초기화해준후

    v-model로 바인딩해주고 is-range속성을 추가하면 기간선택이 date-picker가 된다.

    <script>
    	const rangeDate = ref({
    	  start: null,
    	  end: null
    	})
    </script>
    <template>
    	<VDatePicker v-model="rangeDate" is-range mode="date"/>
    </template>


    Multi

    multi의 경우에는 좀 다르게 기능을 구현해야한다

    VDatePicker를 사용하여 v-model로 바인딩을 하면 단일만 선택되어서 docs에서 본 attributes를 이용해서 기능을 구현

     

    attributes에 highlight: true 를 주고 dates리스트를 props로 전달해주면 리스트안에 있는 날짜가 선택되는 구조이므로,

    이를 이용해서 multi 선택 기능을 구현

     

    @dayclick은 선택한 날짜가 return되는데 이때 day.date에 날짜 값이 존재하여 이 값을 리스트에 담아줘야한다.

    그래서 리스트에 값의 존재 여부를 파악하고 값을 추가하고 삭제하는 로직을 추가

    <script>
    	const multiDate = ref([
    	  {
    	    highlight: true,
    	    dates: [] as Date[],
    	  },
    	])
        
    	const toggleDateSelect = (day: any) => {
    	  const index = multiDate.value[0].dates.indexOf(day.date)
    	
    	  if(index === -1) {
                multiDate.value[0].dates.push(day.date)
    	    return
    	  }
    
    	  multiDate.value[0].dates.splice(index,1)
    	}
    </script>
    <template>
        <VDatePicker
              :attributes="multiDate"
              @dayclick="toggleDateSelect"
         />
    </template>

     


    Date Picker Popup

    VDatePicker를 활용해서 datepicker 구현

    open값을 보내서 VCalendar popup을 열고 닫고 구현,

    date날짜를 바인딩하여 처리

     

    popupRef를 활용하여 해당 컴포넌트 외부 클릭시 팝업을 닫히도록 설정

    const showStartDate = ref(false)
    
    const repeatOption = reactive({
      startDate: Date.now(),
      endDate: '',
    })
    <select-date v-model="repeatOption.startDate" @click="showStartDate = !showStartDate"/>
    <app-calendar v-model="repeatOption.startDate" :open="showStartDate"/>
    <script setup lang="ts">
    import {onBeforeUnmount, onMounted, ref} from "vue";
    
    const open = defineModel('open', {default: false})
    const currentDate = defineModel()
    
    const popupRef = ref()
    
    const handleClickOutside = (event: MouseEvent) => {
      if (popupRef.value && !popupRef.value.contains(event.target as Node)) {
        open.value = false 
      }
    }
    
    onMounted(() => {
      document.addEventListener('mousedown', handleClickOutside)
    })
    
    onBeforeUnmount(() => {
      document.removeEventListener('mousedown', handleClickOutside)
    })
    </script>
    
    <template>
    <div v-if="open" ref="popupRef" class="calendar-popup-wrapper">
      <VDatePicker v-model="currentDate" mode="date"/>
    </div>
    </template>

    728x90
    반응형