0π
β
In the end I solved this by doing the following:
- Add an
@input
event to handle when date range is selected properly - Add a
@dayclick
event to add the entered class when a day is selected - Add a timeout to the
handleBlur
method (the@dayClick
event seemed to take a bit of time to fire so the blur animation started before it kicked in) - Add a mutation observer to see if the calendar closes β as the calendar doesnβt have a close event, I needed to see if the calendar was closed without valid date range selected β if this happened and the inputs were emptied, this observer removed the entered class
new Vue({
el: "#app",
data() {
return {
range: {
start: null,
end: null
}
};
},
mounted() {
const overlay = document.querySelector('.filter__overlay');
const config = {
attributes: false,
childList: true,
subtree: true
};
// watch to see if calendar is closed
const observer = new MutationObserver(mutationsList => {
mutationsList.forEach(mutation => {
if (mutation.type === 'childList' &&
mutation.removedNodes.length > 0 &&
mutation.removedNodes[0].classList &&
mutation.removedNodes[0].classList.contains('vc-popover-content')) {
removeClass(this.$refs.filterDateForm);
removeClass(this.$refs.filterDateTo);
}
});
});
observer.observe(overlay, config);
},
methods: {
handleBlur(event) {
const input = event.currentTarget;
setTimeout(() => {
removeClass(input);
}, 150);
},
handleFocus(event) {
event.currentTarget.parentNode.classList.add("entered");
},
handleCalendarBlur() {
changeClass(this.$refs.filterDateForm);
changeClass(this.$refs.filterDateTo);
},
handleCalendarClick() {
this.$refs.filterDateForm.parentNode.classList.add("entered");
this.$refs.filterDateTo.parentNode.classList.add("entered");
},
}
});
function removeClass(input) {
if (input.value === '') {
input.parentNode.classList.remove("entered");
}
}
function changeClass(input) {
if (input.value === '') {
input.parentNode.classList.remove("entered");
} else {
input.parentNode.classList.add("entered");
}
}
@import url 'https://unpkg.com/v-calendar@2.3.4/lib/v-calendar.min.css';
.filter__date-range-holder {
display: flex;
justify-content: space-between;
width: 95%;
}
.filter__date-range-column {
width: calc(50% - 15px);
}
.form__row {
position: relative;
margin: 1.5em 0;
background: white;
}
.form__control {
width: 100%;
border: 1px solid grey;
font-size: 1rem;
line-height: 1.5rem;
color: black;
padding: 0.75em;
background: transparent;
}
.invalid .form__control {
border-color: red;
outline-color: red;
}
.form__control:focus {
border-radius: 0;
}
.form__label {
display: inline-block;
position: absolute;
top: 50%;
left: calc(0.75em + 1px);
transform: translateY(-50%);
z-index: 1;
color: black;
background: white;
transition: all 0.25s ease-in-out;
pointer-events: none;
}
.entered .form__label {
top: 0;
left: 0.5rem;
font-size: 0.6875rem;
line-height: 0.6875rem;
padding: 0.2em;
}
.invalid .form__label {
color: red;
}
<script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
<script src="https://unpkg.com/v-calendar@2.3.4/lib/v-calendar.umd.min.js"></script>
<div id='app'>
<div class="filter__overlay">
<v-date-picker v-model="range" :popover="{ visibility: 'focus' }" is-range @input="handleCalendarBlur" @dayclick="handleCalendarClick">
<template #default="{ inputValue, inputEvents }">
<div class="filter__date-range-holder">
<div class="filter__date-range-column">
<div class="form__row filter__date-range-row">
<label class="form__label filter__date-range-label" for="filter-date-from">From</label>
<input id="filter-date-from" ref="filterDateForm" type="text" name="from" class="form__control form__control--textbox" :value="inputValue.start" v-on="inputEvents.start" @focus="handleFocus" @blur="handleBlur">
</div>
</div>
<div class="filter__date-range-column">
<div class="form__row filter__date-range-row">
<label class="form__label filter__date-range-label" for="filter-date-to">To</label>
<input id="filter-date-to" ref="filterDateTo" type="text" name="to" class="form__control form__control--textbox" :value="inputValue.end" v-on="inputEvents.start" @focus="handleFocus" @blur="handleBlur">
</div>
</div>
</div>
</template>
</v-date-picker>
</div>
</div>
Please note this example works differently to the one in my site β for some reason the one in my site will remove the dates from the inputs if only one date is selected β this one seems to keep it
Source:stackexchange.com