最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - vue Fullcalendar eventRender, add vue component - Stack Overflow

programmeradmin1浏览0评论

I use fullcalendar.io vue extension.

And I want to hook into event render to add actions, but the event callback contains only JS element.

There is a way to inject vue ponent into it?

<FullCalendar
    ref="fullCalendar"
    defaultView="dayGridMonth"
    :firstDay="1"
    :editable="true"
    :draggable="true"
    :timeZone="'UTC'"
    :header="false"
    :events="events"
    :plugins="plugins"
    @eventRender="eventRender"
/>

JS

import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction';

export default {
        ponents: {
            FullCalendar
        },
        data () {
            return {
                loader: false,
                calendar: null,
                plugins: [
                    dayGridPlugin, interactionPlugin
                ],
                events: [
                    {"id":1,"start":"2019-11-25","end":"2019-11-27"},
                    {"id":2,"start":"2019-11-23","end":"2019-11-26"},
                    {"id":3,"start":"2019-11-22","end":"2019-11-25"},
                    {"id":4,"start":"2019-11-21","end":"2019-11-24"}
                ]
            }
        },

        mounted() {

            this.calendar = this.$refs.fullCalendar.getApi();

        },

        methods:{

            eventRender(info){

                console.log(info);

            },
        }
}

For example inside eventRender (this is dirty example of what needed):

eventRender(info){

    $(info.el).append('<ponent-name></ponent-name>');

}

Update Another solution is Vue.extend (Don't know if is a correct way, Any suggestions?):

add a external ponent:

<template>
    <v-btn @click="click" :class="type">
        <slot name="text"/>
    </v-btn>
</template>

<script>
export default {
    name: 'Button',
    props: [
        'type'
    ],
    methods: {
        click() {
            this.$emit('click')
        }
    }
}

</script>

Import into needed ponent

import Vue from "vue"
import Button from "./helpers/Button"
var ActionClass = Vue.extend(Button)

In render function use props and slot to eventRender

eventRender(info){

    let action = new ActionClass({
        propsData: {
             type: 'primary'
        }
    })
    action.$slots.text = 'Click me!'
    action.$mount()
    action.$on('click', () => {
         console.log(info);
    });

    info.el.appendChild(action.$el)

}

I use fullcalendar.io vue extension.

And I want to hook into event render to add actions, but the event callback contains only JS element.

There is a way to inject vue ponent into it?

<FullCalendar
    ref="fullCalendar"
    defaultView="dayGridMonth"
    :firstDay="1"
    :editable="true"
    :draggable="true"
    :timeZone="'UTC'"
    :header="false"
    :events="events"
    :plugins="plugins"
    @eventRender="eventRender"
/>

JS

import FullCalendar from '@fullcalendar/vue'
import dayGridPlugin from '@fullcalendar/daygrid'
import interactionPlugin from '@fullcalendar/interaction';

export default {
        ponents: {
            FullCalendar
        },
        data () {
            return {
                loader: false,
                calendar: null,
                plugins: [
                    dayGridPlugin, interactionPlugin
                ],
                events: [
                    {"id":1,"start":"2019-11-25","end":"2019-11-27"},
                    {"id":2,"start":"2019-11-23","end":"2019-11-26"},
                    {"id":3,"start":"2019-11-22","end":"2019-11-25"},
                    {"id":4,"start":"2019-11-21","end":"2019-11-24"}
                ]
            }
        },

        mounted() {

            this.calendar = this.$refs.fullCalendar.getApi();

        },

        methods:{

            eventRender(info){

                console.log(info);

            },
        }
}

For example inside eventRender (this is dirty example of what needed):

eventRender(info){

    $(info.el).append('<ponent-name></ponent-name>');

}

Update Another solution is Vue.extend (Don't know if is a correct way, Any suggestions?):

add a external ponent:

<template>
    <v-btn @click="click" :class="type">
        <slot name="text"/>
    </v-btn>
</template>

<script>
export default {
    name: 'Button',
    props: [
        'type'
    ],
    methods: {
        click() {
            this.$emit('click')
        }
    }
}

</script>

Import into needed ponent

import Vue from "vue"
import Button from "./helpers/Button"
var ActionClass = Vue.extend(Button)

In render function use props and slot to eventRender

eventRender(info){

    let action = new ActionClass({
        propsData: {
             type: 'primary'
        }
    })
    action.$slots.text = 'Click me!'
    action.$mount()
    action.$on('click', () => {
         console.log(info);
    });

    info.el.appendChild(action.$el)

}
Share Improve this question edited Dec 17, 2019 at 7:25 SergkeiM asked Dec 16, 2019 at 12:30 SergkeiMSergkeiM 4,1786 gold badges40 silver badges73 bronze badges 2
  • Vue is data driven - make a ponent and change its state like: v-for="appended in appendables" ... and in eventRender push to appendables – Estradiaz Commented Dec 16, 2019 at 12:47
  • @Estradiaz thank you for your reply, this way there will 2 calendars one create by FullCalendar second by v-for, the eventRender event is emited when Element is rendered and ready for modifications. – SergkeiM Commented Dec 16, 2019 at 12:52
Add a ment  | 

1 Answer 1

Reset to default 5

UPDATE With fullCalendar V5, there is a slot support, so this hack is not needed anymore.

So what I did in the end is used the Vue.extend() solution (including creating and destroying the ponent manually) Until they will add slots

Full Example (Calendar Component):

<template>
    <FullCalendar
        ref="fullCalendar"
        defaultView="dayGridMonth"
        :events="events"
        :plugins="plugins"
        @eventRender="eventRender"
        @eventDestroy="eventDestroy"
    />
</template>
<script>
    import Vue from "vue"
    import dayGridPlugin from '@fullcalendar/daygrid'
    import FullCalendar from '@fullcalendar/vue'

    //Import Event ponent
    import Event from "./helpers/Event"

    //Init Event ponent
    const EventClass = Vue.extend(Event)

    export default {
        ponents: {
            FullCalendar
        },
        data () {
            return {
                plugins: [
                    dayGridPlugin
                ],
                events: {
                    url: "/api/calendar",
                },
                eventsObj: {}
            }
        },

        methods:{

            //FullCalendar Render event
            eventRender(info){

                //create our ponent instance
                const event = new EventClass({
                    propsData: {
                        event: info.event
                    }
                })

                event.$on('edit', this.edit)

                event.$on('delete', this.delete)

                event.$mount();

                //assign created ponent to our eventObj with uuid as key (to destroy in future)
                this.eventsObj[event._uid] = event;

                //set data-vue="{id}"
                //append our piled ponent to .fc-event
                info.el.setAttribute('data-vue-id', event._uid);
                info.el.appendChild(event.$el)

            },


            //we need to destroy out ponent when element is removed from calendar
            eventDestroy(info){

                //get uuid
                let id = parseInt(info.el.getAttribute('data-vue-id'));

                if(this.eventsObj[id]){

                    //if exist destroy
                    this.eventsObj[id].$destroy(true);

                }
            },

            edit(event){

                console.log("edit Click")

            },

            delete(event){

                console.log("delete Click")

            }
        }
    }
</script>

Event Component:

<template>
    <v-toolbar flat dense height="30px" class="elvation-0">
        <v-btn @click="clickHandler('edit')" color="white">
            <v-icon small>edit</v-icon>
        </v-btn>
        <v-btn @click="clickHandler('delete')" color="white">
            <v-icon small>delete</v-icon>
        </v-btn>
    </v-toolbar>
</template>
<script>
export default {
    name: 'Event',
    props: ['event']
    methods: {
        clickHandler(type) {
            this.$emit(type, this.event)
        }
    }
}
</script>
发布评论

评论列表(0)

  1. 暂无评论