vuejs (3.0)에서 달력 플러그인(flatpickr)을 component로 사용 할 때 시작일, 종료일 지정하기
.vue
<flat-pickr class="input_cal trans calStr" placeholder="시작일" readonly
v-model="info.sdate"
@on-change="stChange"
:config="config('st')" />
<flat-pickr class="input_cal trans calEnd" placeholder="종료일" readonly
v-model="info.edate"
@on-change="edChange"
:config="config('ed')" />
<flat-pickr class="input_cal trans calToay" placeholder="오늘" readonly
v-model="info.today"
:config="configtoday" />
javascript
<script setup>
import { ref, computed, nextTick } from "vue";
import flatPickr from "vue-flatpickr-component";
import "flatpickr/dist/flatpickr.min.css";
import dayjs from "dayjs";
const info = ref({
sdate:"",// 시작일
edate:"",// 종료일
today:"",
});
// 달력 config
const config = computed(() => {
return (no) => {
let conf = null;
// 시작일. 종료일 제한
if(no === "st") {
conf = {
maxDate: order.value.edate,
locale: {
months: {
shorthand:["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"],
longhand: ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
},
weekdays: {
shorthand: ["일", "월", "화", "수", "목", "금", "토"],
longhand: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
}
}
}
}
// 종료일. 시작일 제한
else {
conf = {
minDate: order.value.sdate,
locale: {
months: {
shorthand:["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"],
longhand: ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
},
weekdays: {
shorthand: ["일", "월", "화", "수", "목", "금", "토"],
longhand: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
}
}
}
}
return conf;
}
})
// 달력이 하나일 때
const configtoday = ref();
nextTick( () => {
configtoday.value = {
locale: {
months: {
shorthand: ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"],
longhand: ["01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"]
},
weekdays: {
shorthand: ["일", "월", "화", "수", "목", "금", "토"],
longhand: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
}
}
}
})
// 달력 관련
const stChange = (selectDates, dateStr, instance) => {
info.value.sdate = dateStr;
}
const edChange = (selectDates, dateStr, instance) => {
info.value.edate = dateStr;
}
// dayjs 사용시
// info.today = dayjs(new Date(), "YYYY-MM-DD").format();
</script>
component(ex: Calendar.vue)
<template>
<div class="m_calendar_ar">
<button class="btn_ar" @click="arrowDay('prev')">◀</button>
<div class="m_calendar">
<flat-pickr type="text" class="input_cal trans calStr" placeholder="시작일" readonly v-model="info.today" :config="config" @on-change="checkDay" />
</div>
<button class="btn_ar" @click="arrowDay('next')">▶</button>
</div>
</template>
<script setup>
import { ref, nextTick } from "vue";
import flatPickr from "vue-flatpickr-component";
import "flatpickr/dist/flatpickr.min.css";
import dayjs from "dayjs"
// 달력 정보
const info = ref({
today: "",//
prevBasicDay: "",// 이전 버튼 클릭 시 선택된 날짜용
nextBasicDay: "",// 다음 버튼 클릭 시 선택된 날짜용
})
const config = ref();
//
nextTick(() => {
info.value.today = new Date();
config.value = {
disableMobile: true,
dateFormat: "Y년 n월 j일",// y, m, d
locale: {
months: {
shorthand: ["01월", "02월", "03월", "04월", "05월", "06월", "07월", "08월", "09월", "10월", "11월", "12월"],
longhand: ["01월", "02월", "03월", "04월", "05월", "06월", "07월", "08월", "09월", "10월", "11월", "12월"]
},
weekdays: {
shorthand: ["일", "월", "화", "수", "목", "금", "토"],
longhand: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
}
}
}
})
// 지난 날, 다음 날
const arrowDay = (n) => {
if(n === "prev") {
info.value.prevBasicDay = info.value.today.replace(/년|월|일/g, "").replace(/ /g, "-");
let prevday = dayjs(info.value.prevBasicDay).add(-1, "day").format("YYYY년 M월 DD일");
info.value.today = prevday
} else {
info.value.nextBasicDay = info.value.today.replace(/년|월|일/g, "").replace(/ /g, "-");
let nextday = dayjs(new Date(info.value.nextBasicDay)).add(1, "day").format("YYYY년 M월 DD일");
info.value.today = nextday
}
}
const checkDay = (selectedDates, dateStr, instance) => {
info.value.today = dateStr;
emit("today", info.value.today);
}
// 바뀐 날짜 부모 컴포넌트에 보내기
const emit = defineEmits(["today"]);
</script>
<!--
// 부모 컴포넌트에서 사용 시
<Calendar @today="checkDay" />
...
const checkDay = (value) => {
console.log("today : ", value);
}
-->
component(ex: BoxCalendar.vue) ...
<template>
<div class="box_calendar">
<p class="txt">{{ txt }}</p>
<img src="@/assets/images/icon_calendar_small.svg" alt="">
<flat-pickr type="text" class="cal_input trans calStr" :placeholder="txt"
v-model="cal.checkday" :config="config" @on-change="checkDay" />
</div>
</template>
<script setup>
import { ref, computed, nextTick } from "vue";
import flatPickr from "vue-flatpickr-component";
import "flatpickr/dist/flatpickr.min.css";
import dayjs from "dayjs"
// 바뀐 날짜 부모 컴포넌트에 보내기
const emit = defineEmits(["checkday"]);
//
const props = defineProps({
txt: {
type: String,
defatult: undefined
},
day: undefined,
maxday: null,// 선택 가능한 마지막 날짜
minday: null,// 선택 가능한 최초 날짜
})
//
const cal = ref({
checkday: "",//
maxday: computed(() => {
return props.maxday
}),
minday: computed(() => {
return props.minday
}),
})
if(props.day === undefined) {
cal.value.checkday = new Date();
} else {
cal.value.checkday = props.day;
}
//
const config = computed(() => {
return {
disableMobile: true,
dateFormat: "Y년 m월 j일",// y, n, d
maxDate: cal.value.maxday,///
minDate: cal.value.minday,///
/// mode: "range",
locale: {
/// rangeSeparator : ' ~ ',
months: {
shorthand: ["01월", "02월", "03월", "04월", "05월", "06월", "07월", "08월", "09월", "10월", "11월", "12월"],
longhand: ["01월", "02월", "03월", "04월", "05월", "06월", "07월", "08월", "09월", "10월", "11월", "12월"]
},
weekdays: {
shorthand: ["일", "월", "화", "수", "목", "금", "토"],
longhand: ["일요일", "월요일", "화요일", "수요일", "목요일", "금요일", "토요일"],
}
}
}
});
const checkDay = (selectedDates, dateStr, instance) => {
cal.value.checkday = dateStr;
emit("checkday", cal.value.checkday);
}
</script>
<!--
# day : 보여지는 날짜(없으면 오늘 날짜)
# maxday : 시작일 달력에서 선택 가능한 마지막 날짜
# minday : 종료일 달력에서 선택 가능한 최초 날짜
@ checkday : 바뀐 날짜를 부모로 전달
// 부모 컴포넌트에서 사용 시(단일)
<BoxCalendar txt="타이틀" :day="보여지는 날짜" @checkday="바뀐 날짜 받는 함수" />
...
const 바뀐 날짜 받는 함수 = (value) => {
console.log("checkday : ", value);
}
// 부모 컴포넌트에서 사용 시(시작일 ~ 종료일)
<BoxCalendar txt="시작일타이틀" :day="cal.startday"
:maxday="cal.endday" @checkday="cal.startday = $event" />
<BoxCalendar txt="종료일타이틀" :day="cal.endday"
:minday="cal.startday" @checkday="cal.endday = $event" />
-->
component(ex: RangeCalendar.vue) ...
<template>
<flat-pickr class="input_cal trans calStr" :config="config()" readonly v-model="info.rangedate" />
<a href="#" id="movefocus" class="hidden"></a>
</template>
<script setup>
import { ref, computed } from "vue"
import dayjs from "dayjs"
import flatPickr from "vue-flatpickr-component"
import "flatpickr/dist/flatpickr.min.css"
//
const emit = defineEmits(["range"])
//
const props = defineProps({
maxday: null, // 선택 가능한 마지막 날짜
rangedate: null,
customrange: false, // true로 수정되면 1주일전 고정이 아니라 임의의 기긴을 선택할 수 있게 변경
})
//
const info = ref({
maxday: computed(() => {
return props.maxday
}),
rangedate: ""
})
info.value.rangedate = props.rangedate;
//
const config = computed(() => {
return () => {
let conf = null;
conf = {
disableMobile: true,
mode: "range",
maxDate: info.value.maxday,
locale: {
rangeSeparator: ' ~ ',
months: {
shorthand: ['01월', '02월', '03월', '04월', '05월', '06월', '07월', '08월', '09월', '10월', '11월', '12월'],
longhand: ['01월', '02월', '03월', '04월', '05월', '06월', '07월', '08월', '09월', '10월', '11월', '12월']
},
weekdays: {
shorthand: ['일', '월', '화', '수', '목', '금', '토'],
longhand: ['일요일', '월요일', '화요일', '수요일', '목요일', '금요일', '토요일']
}
},
onChange: function(selectedDates, dateStr, instance) {
if(!props.customrange) {
// 날짜 한 번 클릭하면 6일전 날짜를 시작날짜로 추가
selectedDates.unshift(new Date(dayjs(selectedDates).add(-6, "days")));
//
info.value.rangedate = dayjs(selectedDates[0]).format("YYYY-MM-DD") + " ~ " + dayjs(selectedDates[1]).format("YYYY-MM-DD");
emit("range", info.value.rangedate);
// 날짜 바꾼 달력 다시 클릭 시 바로 클릭이 안되고 다른데 클릭했다가 클릭해야 클릭되는 현상 때문에 focus를 다른데로 이동
setTimeout(() => {
document.querySelector("#movefocus").focus();
}, 70);
} else {
if(selectedDates[1] !== undefined) {
info.value.rangedate = dayjs(selectedDates[0]).format("YYYY-MM-DD") + " ~ " + dayjs(selectedDates[1]).format("YYYY-MM-DD");
emit("range", info.value.rangedate);
}
}
}
}
return conf
}
})
</script>
<!--
# maxday : 달력에서 선택 가능한 마지막 날짜
# rangedate : 선택한 기간
// 컴포넌트에서 사용 시
<RangeCalendar :rangedate="info.rangedate" @range="rangeDate" />
<RangeCalendar :rangedate="info.rangedate" @range="rangeDate" :customrange="true" />
...
import dayjs from "dayjs"
...
const info = ref({
rangedate: `${dayjs(new Date()).add(-6, "day").format("YYYY-MM-DD")} ~ ${dayjs(new Date()).format("YYYY-MM-DD")}`
})
...
const rangeDate = (e) => {
info.value.rangedate = e;
console.log(info.value.rangedate);
}
-->
날짜가 변경되면 set(option, value)을 이용해서 다른 달력의 옵션을 설정하는 cdn 형태와는 다르게 컴포넌트에서는 :config="config" 를 사용해서 다른 달력의 옵션을 설정할 수 있다
끝.