nathanreyes / v-calendar

An elegant calendar and datepicker plugin for Vue.
https://vcalendar.io
MIT License
4.38k stars 857 forks source link

Wrapping v-date-picker in custom component for general use #222

Open Arwany opened 5 years ago

Arwany commented 5 years ago

I tried wrapping the date picker in a component to use it on multiple places in my web app.

One thing is still not working for me: getting correct props values.

Here is what I did:

<template>

    <v-date-picker
            mode='range'
            v-model='selectedDates'
            :min-date="new Date()"
            popover-visibility="focus"
            :show-day-popover="false"
            @input="handleInput"
            show-caps>
        <div slot-scope="props">
            <input type="text" class="form-control calendar-input"
                   placeholder="Please select your dates"
                   :value="props.inputValue"
                   readonly/>
            <button class="btn btn-sm btn-calendar" disabled>
                <i class="fa fa-calendar"></i>
            </button>

            <button v-if="selectedDates !== null" @click="clearData" class="btn btn-sm btn-clear">
                <i class="fa fa-times"></i>
            </button>

            <span class="spn-nights" v-if="selectedDates !== null">{{ getNightSpan(selectedDates) }} Nights</span>

        </div>

    </v-date-picker>

</template>

<script>

    import VCalendar from 'v-calendar';
    import 'v-calendar/lib/v-calendar.min.css';

    const msInDay = 1000 * 60 * 60 * 24;

    export default {
        name: "Calendar",

        props: {
            value: {
                type: Object
            },
        },

        watch: {
            value: function (value) {
                this.selectedDates = value;
            }
        },

        model: {
            prop: 'value',
            event: 'input'
        },

        data() {
            return {
                drag: null,
                selectedDates: null,
            }
        },

        computed: {
            daySpan() {
                const span = this.getNightSpan(this.drag || this.date);
                return (span && `${span} days`) || '';
            },
        },

        mounted() {
            this.selectedDates = this.value;
        },

        methods: {
            getNightSpan(range) {
                if (!range) return 0;
                return (range.end - range.start) / msInDay;
            },

            handleInput(e) {
                this.$emit('input', this.selectedDates);
                this.$emit('changed');
            },
            clearData(e) {
                this.selectedDates = null;
                this.$emit('input', this.selectedDates);
                this.$emit('cleared');
            },
        },
    }
</script>

And I am using it like this:

<template>
...
<cal v-model="dates" @cleared="cleared" @changed="cleared"></cal>
...
</template>
<script>
    import Cal from './Calendar';
    export default {

        components: {
            Cal
        },
        data(){
                return {
                        dates: null,
                }
        },

        mounted(){
                this.dates = loadedDates;
        },

    }

</script>

This should give a result like this: Empty: image After selecting: image

But if the item loadedDatesis not null, the result looks like this: image

and: image

The calendar is actually correctly setup, only the props are not updating.

How can make the change to the props when loading the result? Is there a better way to wrap the calendar than I did above, because I feel that I am over doing it.

Thank you so much for this amazing work.

Arwany commented 5 years ago

I am using the version: "v-calendar": "^0.9.7",

sluxzer commented 3 years ago

no one answer this question, cause i have same issue