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 byv-for
, theeventRender
event isemited
when Element is rendered and ready for modifications. – SergkeiM Commented Dec 16, 2019 at 12:52
1 Answer
Reset to default 5UPDATE 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>