I cannot display the events in the fullcalendar, I am using vue and vuex to develop a laravel nova compoment with a modal window, I already try in some many ways but without success. I hope anyone can help me.
my store is this:
import Vuex from 'vuex';
Nova.booting((Vue, router, store) => {
Vue.component('fullcalendar', require('./components/Tool'))
Vue.use(Vuex);
Nova.store = new Vuex.Store({
state: {
event: [],
events: [],
},
mutations: {
SET_EVENT(state, event) {
state.event = event;
},
ADD_TO_EVENTS(state, event) {
state.events.push(event);
}
},
actions: {
setEvent(context, event) {
context.commit('SET_EVENT', event);
},
addToEvents(context, event) {
context.commit('ADD_TO_EVENTS', event);
},
},
getters: {
event: state => state.event,
events: state => state.events,
},
});
})
my Tool.vue is this
<template>
<div>
event {{ events }}
<FullCalendar ref="fullcalendar" :options="calendarOptions"/>
<modal :show="showModal" #close="showModal = false"></modal>
<button id="show-modal" #click="showModal = true"></button>
</div>
</template>
<script>
import FullCalendar from '#fullcalendar/vue';
import dayGridPlugin from '#fullcalendar/daygrid';
import timeGridPlugin from '#fullcalendar/timegrid';
import listGridPlugin from '#fullcalendar/list';
import interactionPlugin from '#fullcalendar/interaction';
import modal from './Modal.vue';
export default {
props: ['resourceName', 'resourceId', 'panel'],
components: {
modal,
FullCalendar, // make the <FullCalendar> tag available
},
data() {
return {
showModal: false,
calendarOptions: {
plugins: [ dayGridPlugin, timeGridPlugin, listGridPlugin, interactionPlugin ],
initialView: 'dayGridMonth',
events: this.events,
editable: true,
select: this.handleDateClick,
eventClick: this.handleEventClick,
buttonText: {
today: 'Today',
month: 'Month',
week: 'Week',
day: 'Day',
list: 'Agenda'
},
headerToolbar : {
end: 'prevYear,prev today next,nextYear',
center: 'title',
start: 'dayGridMonth,timeGridWeek,timeGridDay listMonth',
},
stickyHeaderDates: true,
aspectRatio: 2.4,
navLinks: true,
selectable: true,
nowIndicator: true,
dayMaxEventRows: true,
dayMaxEvents: 10,
moreLinkClick: 'popover',
businessHours: {
daysOfWeek: [ 1, 2, 3, 4, 5 ], // Monday - Thursday
startTime: '8:00',
endTime: '18:00',
}
}
}
},
mounted() {
this.showModal = false;
},
computed: {
events: () => {
return Nova.store.getters.events;
},
},
methods: {
handleDateClick(arg) {
const event = {
title:'something',
start: moment(arg.start).format('YYYY-MM-DD'),
end: moment(arg.end).format('YYYY-MM-DD'),
allDay: true,
};
Nova.store.dispatch('setEvent', event);
this.showModal = true;
},
handleEventClick(event) {
this.showModal = true;
},
},
}
</script>
my modal window file is this
<template>
<div>
event {{ events }}
<FullCalendar ref="fullcalendar" :options="calendarOptions"/>
<modal :show="showModal" #close="showModal = false"></modal>
<button id="show-modal" #click="showModal = true"></button>
</div>
</template>
<script>
import FullCalendar from '#fullcalendar/vue';
import dayGridPlugin from '#fullcalendar/daygrid';
import timeGridPlugin from '#fullcalendar/timegrid';
import listGridPlugin from '#fullcalendar/list';
import interactionPlugin from '#fullcalendar/interaction';
import modal from './Modal.vue';
export default {
props: ['resourceName', 'resourceId', 'panel'],
components: {
modal,
FullCalendar, // make the <FullCalendar> tag available
},
data() {
return {
showModal: false,
calendarOptions: {
plugins: [ dayGridPlugin, timeGridPlugin, listGridPlugin, interactionPlugin ],
initialView: 'dayGridMonth',
events: this.events,
editable: true,
select: this.handleDateClick,
eventClick: this.handleEventClick,
buttonText: {
today: 'Today',
month: 'Month',
week: 'Week',
day: 'Day',
list: 'Agenda'
},
headerToolbar : {
end: 'prevYear,prev today next,nextYear',
center: 'title',
start: 'dayGridMonth,timeGridWeek,timeGridDay listMonth',
},
stickyHeaderDates: true,
aspectRatio: 2.4,
navLinks: true,
selectable: true,
nowIndicator: true,
dayMaxEventRows: true,
dayMaxEvents: 10,
moreLinkClick: 'popover',
businessHours: {
daysOfWeek: [ 1, 2, 3, 4, 5 ], // Monday - Thursday
startTime: '8:00',
endTime: '18:00',
}
}
}
},
mounted() {
this.showModal = false;
},
computed: {
events: () => {
return Nova.store.getters.events;
},
},
methods: {
handleDateClick(arg) {
const event = {
title:'something',
start: moment(arg.start).format('YYYY-MM-DD'),
end: moment(arg.end).format('YYYY-MM-DD'),
allDay: true,
};
Nova.store.dispatch('setEvent', event);
this.showModal = true;
},
handleEventClick(event) {
this.showModal = true;
},
},
}
</script>
Do you have any clue why I can see the event in the calendar?
I appreciate any help
Thks,
I had the same problem.
I put the calendaroptions in computed
you can check this repository (Vue-vuex)
https://github.com/fullcalendar/fullcalendar-example-projects
Related
I am using FullCalendar and Vue.
I am trying to reload the events once the refreshCal() is triggered and so render the calendar on the screen with refetchEvents.
I have to main components:
The Calendar: here is the code
<script>
import FullCalendar from '#fullcalendar/vue'
import timeGridPlugin from '#fullcalendar/timegrid'
import resourceTimelinePlugin from '#fullcalendar/resource-timeline'
import calendarEdit from '../pages/calendar/edit'
export default {
components: {
FullCalendar
},
data() {
return {
calendarOptions: {
plugins: [ timeGridPlugin, resourceTimelinePlugin ],
schedulerLicenseKey: 'CC-Attribution-NonCommercial-NoDerivatives',
initialView: 'timeGridWeek',
refetchResourcesOnNavigate: true,
//eventSources: ['/api/calendar/json'],
events: '/api/calendar/json',
eventDisplay: 'block',
contentHeight: 'auto',
nowIndicator: true,
locale: 'en-gb',
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'timeGridWeek, timeGridDay'
},
businessHours: [ // specify an array instead
{
daysOfWeek: [ 1, 2, 3, 4, 5 ], // Monday, Tuesday, Wednesday
startTime: '08:00', // 8am
endTime: '20:00' // 6pm
},
{
daysOfWeek: [ 6 ], // Thursday, Friday
startTime: '9:00', // 10am
endTime: '14:00' // 4pm
}
],
slotMinTime: '07:00:00',
slotMaxTime: '24:00:00',
expandRows: true,
eventClick: this.eventModal,
}
}
},
methods: {
eventModal(args) {
let modalProps = {
'event': args.event
}
this.$buefy.modal.open({
props: modalProps,
parent: this,
component: calendarEdit,
hasModalCard: true,
trapFocus: true
})
}
}
}
</script>
<template>
<FullCalendar ref="calsession" :options="calendarOptions"/>
</template>
A modal component to edit the event:
<script>
export default {
data() {
return {
session: {},
startDate: {},
startTime: {},
endTime: {},
message: {}
}
},
props: {
event: {
required: true
}
},
methods: {
getSession() {
this.$http.get(`/api/sessions/${this.event.id}/edit`)
.then( (result) => {
this.session = result.data;
this.startDate = new Date(result.data.start_at)
this.startTime = new Date(result.data.start_at)
this.endTime = new Date(result.data.finish_at)
})
},
update(event) {
this.saving = true;
this.$http.put(`/api/sessions/${this.event.id}`, {
startDate: this.$moment(this.startDate).utc().format('YYYY-MM-DD'),
startTime: this.$moment(this.startTime).utc().format('hh:mm'),
endTime: this.$moment(this.endTime).utc().format('hh:mm')
}).then((response) => {
this.refreshCal()
//this.close()
})
},
refreshCal() {
this.$log(this.$parent.$parent.$refs)
this.$parent.$parent.$refs.calsession.refetchEvents()
}
},
created() {
this.getSession()
}
}
</script>
I have been trying
this.$parent.$parent.$refs.calsession.$emit('refetch-events')
as found in FullCalendar documents and various researches on the internet but it has never worked.
$emit('refetch-events') or $emit('refetchEvents') doens't do anything.
Just for information: this.$parent.$parent.$refs gives the refs to FullCalendar.
Any suggestion?
Thank you all for any kind of help.
if using the official Vue component for Fullcalendar: #fullcalendar/vue
don't need to use emit but get the Calendar object through the getApi method:
let calendar = this.$parent.$parent.$refs.calsession.getApi()
and so using the method refetchEvents:
calendar.refetchEvents()
I am using CKEditor5 with Vue. In my Vuex store, I have the following property:
const state = {
EditMode: false,
}
On a button click by a user with permission, I modify the Vuex store. If EditMode: true, I want to display the in-line editor. Else, display the raw HTML editorData (the user is not authorized to edit, or not in edit mode). I do that below:
<template>
<vx-card :title="editorName" v-if="this.$store.state.EditMode">
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig"></ckeditor>
</vx-card>
<vx-card :title="editorName" v-else>
<div v-html="editorData"></div>
</vx-card>
</template>
<script>
import InlineEditor from '#ckeditor/ckeditor5-build-inline'
export default {
name: "RichTextEditor",
props: {
editorName: {
type: String,
required: true,
},
},
data() {
return {
loaded: false,
time: null,
timeElapsedSinceEdit: 0,
editor: InlineEditor,
editorData: 'New entry!',
editorConfig: {
toolbar: {
items: [
'|',
'heading',
'fontFamily',
'fontSize',
'fontColor',
'bold',
'underline',
'italic',
'alignment',
'link',
'highlight',
'superscript',
'subscript',
'|',
'indent',
'outdent',
'|',
'blockQuote',
'horizontalLine',
'imageUpload',
'insertTable',
'mediaEmbed',
'undo',
'redo'
]
},
language: 'en',
image: {
toolbar: [
'imageTextAlternative',
'imageStyle:full',
'imageStyle:side'
]
},
table: {
contentToolbar: [
'tableColumn',
'tableRow',
'mergeTableCells',
'tableCellProperties',
'tableProperties'
]
},
},
}
},
// Below code is situation-specific and not completely relevant
watch: {
editorData: function() {
if (this.loaded) {
this.upsertData()
}
}
},
methods: {
async pollData() {
await
this.$http.get('/api/rte/' + this.editorName)
.then((response) => {
this.editorData = response.data.content
})
.catch((error) => {
if (window.environment == "production") {
location.href = 'pages/error-500/'
} else {
console.log(error.stack)
}
})
this.loaded = true;
},
async upsertData() {
console.log('up')
await
this.$http.post('/api/rte/' + this.editorName + '/upsert', {
data: this.editorData,
})
.then((response) => {
this.$vs.notify({
title: 'Action Completed',
text: response.data.message,
color: 'success',
position: 'top-right'})
})
.catch((error) => {
if (window.environment == "production") {
location.href = 'pages/error-500/'
} else {
console.log(error)
}
})
},
},
created() {
this.pollData();
},
}
</script>
This works, but the in-line styling isn't respected with v-html (sizing and centering). If this.$store.state.EditMode: false, I get the following output:
If this.$store.state.EditMode: true I get this in the in-line editor (as expected).
Raw HTML (editorData property after pollData() is called)
<figure class="image image_resized" style="width:25.51%;"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTRJO0xRohucbxcjlRoiRaw2cWYTbilYch5NQ&usqp=CAU" alt="Free clipart megaphone announcement public domain vectors - Clipartix"></figure><h2 style="text-align:center;"><span style="color:hsl(30,75%,60%);"><strong>We have a new Intranet!</strong></span></h2><p style="text-align:center;">Summer / Fall Wellness Challenge Link</p>
Research showed that Vue's v-html doesn't respect scoped styling. I'm not entirely sure how that applies to in-line styling. To test output, I replaced my else with the raw HTML and got the same visual output as when I used v-html:
<vx-card :title="editorName" v-else>
<figure class="image image_resized" style="width:25.51%;"><img src="https://encrypted-tbn0.gstatic.com/images?q=tbn%3AANd9GcTRJO0xRohucbxcjlRoiRaw2cWYTbilYch5NQ&usqp=CAU" alt="Free clipart megaphone announcement public domain vectors - Clipartix"></figure><h2 style="text-align:center;"><span style="color:hsl(30,75%,60%);"><strong>We have a new Intranet!</strong></span></h2><p style="text-align:center;">Summer / Fall Wellness Challenge Link</p>
</vx-card>
What is the proper way to disable the inline editor and maintain visual consistency?
<template>
<vx-card :title="editorName" v-if="loaded">
<ckeditor :editor="editor" v-model="editorData" :config="editorConfig" :readonly="editorDisabled" :disabled="editorDisabled" ></ckeditor>
</vx-card>
</template>
//...
watch:{
'$store.state.EditMode'(value, oldValue) {
if(value) {
this.editorDisabled = false;
} else {
this.editorDisabled = true;
}
},
},
//...
Question answered here:
https://github.com/ckeditor/ckeditor5-vue/issues/154
I hope everyone's fine
I'm trying to make the show-select feature work on Vuetify 2.0.x datatables with SSR pagination, with no luck at all.
We were working on vuetify 1.5.x up until now and we changed since it was troubling in there too.
Here's a codepen
I'm just using show-select docs are not further specific
You have missed item-key="unique column name" in v-data-table
here is the codepen
https://codepen.io/manojkmishra/pen/OJMNjzq?editors=1010
Template part
<v-app id="inspire">
<div>
{{msg}}
<v-data-table show-select v-model="selected"
:headers="headers"
:items="desserts"
:options.sync="options"
:items-per-page="5"
:server-items-length="totalDesserts"
:loading="loading"
class="elevation-1"
item-key="name"
></v-data-table>
</div>
</v-app>
Script part
<script>
export default {
data () {
return { selected: [],
totalDesserts: 0,
desserts: [],
loading: true,
options: {},
headers: [
{
text: 'Dessert (100g serving)',
align: 'start',
sortable: false,
value: 'name',
},
{ text: 'Calories', value: 'calories' },
{ text: 'Fat (g)', value: 'fat' },
{ text: 'Carbs (g)', value: 'carbs' },
{ text: 'Protein (g)', value: 'protein' },
{ text: 'Iron (%)', value: 'iron' },
],
}
},
watch: {
options: {
handler () {
this.getDataFromApi()
.then(data => {
this.desserts = data.items
this.totalDesserts = data.total
})
},
deep: true,
},
},
computed: {
msg() {
console.log('msg-',this.selected)
return this.selected
}
},
mounted () {
this.getDataFromApi()
.then(data => {
this.desserts = data.items
this.totalDesserts = data.total
})
},
methods: {
getDataFromApi () {
this.loading = true
return new Promise((resolve) => {
const { sortBy, sortDesc, page, itemsPerPage } = this.options
let items = this.getDesserts()
const total = items.length
if (sortBy.length === 1 && sortDesc.length === 1) {
items = items.sort((a, b) => {
const sortA = a[sortBy[0]]
const sortB = b[sortBy[0]]
if (sortDesc[0]) {
if (sortA < sortB) return 1
if (sortA > sortB) return -1
return 0
} else {
if (sortA < sortB) return -1
if (sortA > sortB) return 1
return 0
}
})
}
if (itemsPerPage > 0) {
items = items.slice((page - 1) * itemsPerPage, page * itemsPerPage)
}
setTimeout(() => {
this.loading = false
resolve({
items,
total,
})
}, 1000)
})
},
getDesserts () {
return [
{
name: 'Frozen Yogurt',
calories: 159,
fat: 6.0,
carbs: 24,
protein: 4.0,
iron: '1%',
},
{
name: 'Ice cream sandwich',
calories: 237,
fat: 9.0,
carbs: 37,
protein: 4.3,
iron: '1%',
},
]
},
},
}
</script>
I am able to pick up fire emitgetcartitems but for some reason the other listener, emitaddnotes, is not firing handleAddNotes(). I checked in context of the component as well by checking this.$listeners and I only saw emitgetcartitems listed for it. I'm not sure why the other event is not working at all.
blade template
<div id = "app">
<Modal
:modal-type="modalType"
:selected-product="selectedProduct"
:variant-data="variantData"
#emitgetcartitems="handleGetCartItems"
#emitaddnotes="handleAddNotes"
>
</Modal>
<Cart>
</Cart>
</div>
app.js
window.Vue = require('vue');
window.axios = require('axios');
Vue.component('Modal',
require('./components/Modal.vue').default);
new Vue({
el: "#app",
data() {
return {
modalType: null,
orderNotes: null,
couponCode: null,
selectedProduct: {},
variantData: [],
cart: {}
}
},
methods: {
handleChangeTab: function(tab) {
this.activeTab = tab
},
handleHideFlashMsg: function() {
this.flashStatus = false
},
handleAddNotes: function(){
console.log("!!!!!!!")
},
handleGetCartItems: function() {
axios
.get('/api/a-cart')
.then(response => {
this.cart = response.cart;
});
},
}
)}
Modal.vue
<template>
<div>
<button v-on:click="addNotes()"></button>
</div>
</template>
<script>
export default {
data() {
return {
couponInput: '',
}
},
props: {
selectedProduct: {type: Object},
orderNotes: {type: String},
couponCode: {type: String}
},
methods: {
getCartItems: function() {
console.log("GET CART")
this.$emit('emitgetcartitems')
},
addNotes: function() {
console.log("ADD NOTES")
this.$emit('emitaddnotes')
},
}
}
</script>
I tried to add Quill Emojis to editor but I am getting console error as
Uncaught ReferenceError: Quill is not defined
I am using Laravel 5.6 and vue js and definately new to vue and its components so I may sound silly to you but for the past 3 days I am searching on the google for the solution and even contacted author of vue2editor on github here is the link
This is what I have tried so far:
vue2editor.vue
<template>
<div id="app">
<vue-editor v-model="content"></vue-editor>
</div>
</template>
<script>
import { VueEditor, Quill } from 'vue2-editor';
import Emoji from 'quill-emoji/dist/quill-emoji';
Quill.register('modules/quill-emoji', Emoji);
export default {
name: 'vue2editor',
components: { VueEditor },
data() {
return {
content: "<h1>Some initial content</h1>",
editorSettings: {
modules: {
toolbar: {
container: [
[{'size': ['small', false, 'large']}],
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ 'header': 1 }, { 'header': 2 }],
[{ 'list': 'ordered' }, { 'list': 'bullet' }],
[{ 'script': 'sub' }, { 'script': 'super' }],
[{ 'indent': '-1' }, { 'indent': '+1' }],
[{ 'direction': 'rtl' }],
[{ 'header': [1, 2, 3, 4, 5, 6, false] }],
[{ 'color': [] }, { 'background': [] }],
[{ 'font': [] }],
[{ 'align': [] }],
['clean'],
['link', 'image', 'video'],
['emoji'],
],
handlers: {
'emoji': function () {}
},
},
toolbar_emoji: true,
short_name_emoji: true,
textarea_emoji:true,
},
},
text: null,
};
},
};
</script>
I even tried the method mentioned by one of the user on github for Quill-Emoji, here is the link.
I came here with lots of hopes; if anyone here is to help me out, at least tell me what I am missing will be more than a help for me.
Quill.register({
'formats/emoji': Emoji.EmojiBlot,
'modules/short_name_emoji': Emoji.ShortNameEmoji,
'modules/toolbar_emoji': Emoji.ToolbarEmoji,
'modules/textarea_emoji': Emoji.TextAreaEmoji}, true);
you need register the model, add the up code to you code.
Edit:
//1) Add plugin to laravel mix
const mix = require('laravel-mix')
mix.webpackConfig(webpack => {
return {
plugins: [
new webpack.ProvidePlugin({
"window.Quill": "quill/dist/quill.js",
Quill: "quill/dist/quill.js"
})
]
};
});
//2 example vue file
<template>
<div class="mt-1">
<vue-editor
ref="editor"
v-model="content"
:editor-toolbar="customToolbar"
:editorOptions="editorSettings"
/>
</div>
</template>
<script>
import { VueEditor, Quill } from "vue2-editor";
import Emoji from "quill-emoji/dist/quill-emoji";
Quill.register("modules/emoji", Emoji);
export default {
components: {
VueEditor,
},
props: {
bubble: Object,
contentCol: {
type: String,
},
},
data() {
return {
edit: false,
content: "<b>Content is here</b>",
customToolbar: [["bold", "italic", "underline"], ["link"], ["emoji"]],
editorSettings: {
modules: {
"emoji-toolbar": true,
"emoji-textarea": true,
"emoji-shortname": true,
},
},
};
},
beforeDestroy() {},
};
</script>
<style src="quill-emoji/dist/quill-emoji.css"/>