Utilize Vue Fullcalendar's eventRender feature to seamlessly incorporate Vue components into your

I am utilizing the fullcalendar.io vue extension.

I would like to customize event rendering in order to add actions, but the event callback only contains JavaScript elements.

Is there a way to inject a vue component into it?

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

JavaScript

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

export default {
        components: {
            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);

            },
        }
}

As an example inside the eventRender function (here is a rough example of what's needed):

eventRender(info){

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

}

Update: Another solution involves using Vue.extend (Not sure if this is the correct approach, any suggestions?):

To add an external component:

<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 the required component:

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

In the render function, utilize props and slot for the eventRender method:

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)

}

Answer №1

UPDATE: FullCalendar V5 now supports slots, eliminating the need for this hack.

In the end, I opted for the Vue.extend() solution by manually creating and destroying the component until slots are added. View the issue here.

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 component
    import Event from "./helpers/Event"

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

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

        methods:{
            eventRender(info){

                const event = new EventClass({
                    propsData: {
                        event: info.event
                    }
                })

                event.$on('edit', this.edit)
                event.$on('delete', this.delete)
                event.$mount();

                this.eventsObj[event._uid] = event;

                info.el.setAttribute('data-vue-id', event._uid);
                info.el.appendChild(event.$el)

            },

            eventDestroy(info){

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

                if(this.eventsObj[id]){
                    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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Calling an ajax request to view a JSON pyramid structure

My experience with ajax is limited, so I would appreciate detailed answers. I have a Pyramid application where I need to load information via ajax instead of pre-loading it due to feasibility issues. I want to retrieve the necessary information through a ...

Reflections on the Javascript Prototype Design Pattern

After using a Javascript revealing module pattern, I'm now transitioning to a new approach which seems to be working. However, I'm not entirely sure if I'm following the best practices. Specifically, I want to know if my method of preserving ...

The sorting function is failing to produce the expected order of values

Currently, I am working on a feature to sort an array of objects based on user-selected values. Strangely, the function returns the same result no matter which case is executed. I have thoroughly checked each case and they are functioning correctly; howeve ...

Looking for a way to utilize a Devise user account in an unconfirmed or locked state for AJAX interactions?

Currently, I am attempting to integrate the devise views utilizing JS to manage the responses. While I aim to utilize the default devise error messages, I am facing difficulty in isolating individual types of errors such as unconfirmed or locked accounts d ...

Tips for sending a set to a directive in angular.js?

Forgive me for my confusion. I am passing the name of a collection to my directive: <ul tag-it tag-src="preview_data.preview.extract.keywords"><li>Tag 1</li><li>Tag 2</li></ul> This is how the directive is defined: a ...

How to Utilize Raw HTML in GWT with the Power of Jquery/Javascript?

Below is the HTML code snippet: <!DOCTYPE html> <html> <head> <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script> <script> $(document).ready(function(){ $("button").click(function( ...

Determine whether there are three or more identical values when comparing two objects in typescript

Hello there, I am in need of some assistance as I am unsure where to begin. Any help would be greatly appreciated. Here are the two objects I have: const Questions = { five: "c" four: "c" one: "a" three: "a" two ...

How can you utilize a computed property in a Vue component to select all the text within it?

When using $event.target.select(), I usually can select all the text. However, in this scenario, it seems to be selecting everything and then replacing the selection with the computed property. How can I select all after the computed property has finished? ...

Regular expression to detect a space that is escaped

Given a string: rsync -r -t -p -o -g -v --progress --delete -l -H /Users/ken/Library/Application\ Support/Sublime\ Text\ 3/Packages /Users/ken/Google\ Drive/__config-GD/ST3 Attempting to find a regex pattern that matches spaces, but ex ...

Ways to implement JavaScript code in Angular 7 application

I am attempting to create a collapsible navigation bar using MaterializeCSS for mobile screens and I plan to incorporate JavaScript code into it. Can you advise where I should place this JavaScript code? Below is the snippet of code that I intend to inclu ...

What is the best method for storing pug-formatted data in a database?

I am currently developing a JavaScript application where I utilize pug for templates and diskdb for storing data. Within my content, I have implemented pug syntax which may appear in the following format: p some content here p some more content here p: # ...

A few of the npm packages that have been installed globally are not functioning properly

After installing npm globally, I checked its version using npm -v and it displayed correctly as 7.13.0. Similarly, I installed heroku-cli globally, but when I ran heroku --version, it returned the error message: C:\Users\MyName\AppData&bso ...

JavaScript data structures used to hold all modified input fields within a document

I am currently working on a project where I have a dynamically generated document using Odoo. The document consists of multiple divs, each containing different types of input boxes such as checkboxes, text fields, and numbers. Currently, every time a user ...

Issue with font selection in Fabric.js

I am currently working with fabric js version 1.7.22 alongside angular 7 to create a text editor. I have encountered an issue when trying to add text to the canvas using a custom font as shown in the code snippet below. var canvas= new fabric.Canvas(&apos ...

Error encountered: The JSON format provided for Spotify Web-API & Transfer User's Playback is invalid

Utilizing the spotify-web-api-js has been a smooth experience for me when interacting with Spotify Web API. However, whenever I attempt to use the transferMyPlayback() method to switch devices, I consistently run into an error response indicating a malfor ...

Understanding the difference between Parameters in Javascript and Java

Currently, I am facing an issue where I am losing some information while sending an ajax request to a servlet. The specific parameter that I am losing data from is the "comment" parameter. Below are the last 4 lines of my ajax code: var params = "name=" + ...

Indicate the node middleware without relying on the port number

My website is hosted at mywebsite.com and I am using node and express for middleware services, pointing to mysite.com:3011/api. The website is hosted statically on Ubuntu 16 (Linux) and the middleware is run separately using pm2 (node server). I want to b ...

Steps for repairing a damaged vuejs project following the inclusion of the "less" and "less-loader" modules

I recently set up a basic vuejs project in IntelliJ and decided to integrate Less into it. However, when I executed "npm install -D less less-loader," an error occurred that I can't seem to resolve. I attempted to downgrade webpack and less-loader wit ...

A bot responsible for assigning roles never fails to remove a role when necessary

My goal was to develop a bot that automatically assigns users a role based on the language they speak in a bilingual server. However, when I tried to assign myself the Czech role, it added the role but failed to remove the rest: const Discord = require(&a ...

Declaring an object in the form of a function

I need some assistance with calling a method that is declared like an object in the following code. What approach should I take to call the function properly? var draw = function() { anotherFunction(); } draw(); Upon execution, an error stating "Typ ...