Full Calendar Component did not render properly on Dialog - vue.js

Using Full Calendar in Vue3 Composition. When using the calendar component in quasar dialog, the initial rendering is incorrect, but after going to the prev/next month, the render turns out fine.
<template>
<FullCalendar :options="calendar" />
</template>
<script setup lang="ts">
import '#fullcalendar/core/vdom'; // solves problem with Vite
import FullCalendar, { CalendarOptions } from '#fullcalendar/vue3';
import dayGridPlugin from '#fullcalendar/daygrid';
import interactionPlugin from '#fullcalendar/interaction';
import { ref } from 'vue';
const calendar = ref<CalendarOptions>({
plugins: [dayGridPlugin, interactionPlugin],
initialView: 'dayGridMonth',
buttonText: {
today: 'Today',
},
events: currentEvents,
displayEventTime: false,
});
Please assist me on this.

Apparently you have use dispatchEvent to resize the window when onMounted, however this solution will have a certain delay once the calendar is loaded in.
onMounted(() => {
setTimeout(function () {
window.dispatchEvent(new Event('resize'));
}, 1);
});

Related

Vue.js - Element Plus - How to test el-dropdown component

I have a problem that I can't trigger el-dropdown menu. I've followed the testing approach done in element-plus repository but couldn't able to simulate mouseenter event and see whether dropdown menu is opened.
my code can be found below.
<template>
<el-dropdown>
<el-icon>
<MoreFilled/>
</el-icon>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item>Send a message</el-dropdown-item>
<el-dropdown-item>Report</el-dropdown-item>
<el-dropdown-item>Block</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script lang="ts" setup>
import { MoreFilled } from '#element-plus/icons-vue';
</script>
and my test code can be found here
import { mount } from "#vue/test-utils";
import { nextTick } from "vue";
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
import EntryCardFooterDropdown from "../EntryCardFooterDropdown.vue";
import { ElTooltip } from "element-plus";
describe('EntryCardFooterDropdown', () => {
it('render', async () => {
const wrapper = mount(EntryCardFooterDropdown)
await nextTick()
const content = wrapper.findComponent(ElTooltip).vm as InstanceType<typeof ElTooltip>
vi.useFakeTimers();
const triggerElm = wrapper.find('.el-tooltip__trigger');
expect(content.open).toBe(false);
await triggerElm.trigger('mouseenter');
vi.runAllTimers();
expect(content.open).toBe(true);
})
})

Unable to add map control to mapbox Nuxt3/Vue3 to zoom

I've created a new Nuxt3 app and I'm playing around with Mapbox.
I got the map to render in my Map.vue component I created, but I'm unable to add controls to it and other options. I just can't get the controls to show.
Here's my component code. Any help would be appreciated.
<template>
<div id="map" class="h-full"></div>
</template>
<script setup lang="ts">
import { onMounted, defineProps } from 'vue';
import axios from 'axios';
import mapboxgl from 'mapbox-gl';
import MapboxGeocoder from '#mapbox/mapbox-gl-geocoder';
const props = defineProps({
mapCoords: {
type: Array,
default: () => []
}
})
onMounted(() => {
createMap();
})
function createMap() {
mapboxgl.accessToken = 'xxxxxxxxxxx';
let map = new mapboxgl.Map({
container: 'map',
center: props.mapCoords,
style: 'mapbox://styles/mapbox/streets-v11',
zoom: 12
});
map.addControl(new mapboxgl.NavigationControl());
}
</script>
<style>
#import '#mapbox/mapbox-gl-geocoder/dist/mapbox-gl-geocoder.css';
</style>
I'm also getting this type unknown warning in my IDE for the center option.

WebGL Earth or globe.gl in VUE.JS

Can I use "WebGL Earth" or "globe.gl" in vue.js? I search a lot but what I found was that there is "react-globe.gl" for react developers, but can't find the same for vue.
If I can use any of them in vue, how can I import and initialize it?
I am currently am using globe.gl with vue 3, got it running like this.
Can also checkout a template repo I have https://github.com/GBerghoff/Globe.gl-with-Vue-3
<template>
<div ref="globeDiv"></div>
</template>
<script>
import Globe from "globe.gl";
import { ref, onMounted } from "vue";
export default {
setup() {
const globeDiv = ref(null);
onMounted(() => {
const myGlobe = Globe();
myGlobe(globeDiv.value).globeImageUrl(
"//unpkg.com/three-globe/example/img/earth-night.jpg"
);
});
return {
globeDiv,
};
},
};
</script>

Gridsome Full Calendar build error - no SSR

I'm trying to use the Full Calendar vue component (https://github.com/fullcalendar/fullcalendar-vue) in a Gridsome project like so:
<template>
<div class="tabStaffManage">
<div>
<FullCalendar
ref="staffCalendar"
class="fullCalendar"
defaultView="dayGridMonth"
:events="calendarEvents"
:plugins="calendarPlugins"
:allDaySlot="false"
:header="{
center: 'dayGridMonth, timeGridDay',
right: 'prev, next'
}"
minTime="09:00:00"
:selectable="true"
maxTime="18:30:00"
#eventClick="onEventClick"
#select="onDateSelect"
:showNonCurrentDates="false"
></FullCalendar>
</div>
</div>
</template>
<script>
import { formatDate } from "#fullcalendar/core"
import FullCalendar from "#fullcalendar/vue"
import timeGridPlugin from "#fullcalendar/timegrid"
import dayGridPlugin from "#fullcalendar/daygrid"
import interactionPlugin from "#fullcalendar/interaction"
export default {
components: {
FullCalendar,
},
data() {
return {
calendarPlugins: [dayGridPlugin, timeGridPlugin, interactionPlugin],
}
},
}
</script>
This, however, produces an error on build:
Could not generate HTML for "/staff/dashboard/":
ReferenceError: Element is not defined
at Object.338 (node_modules/#fullcalendar/core/main.esm.js:102:0)
at __webpack_require__ (webpack/bootstrap:25:0)
at Module.552 (assets/js/page--src-pages-staff-dashboard-vue.ea5234e7.js:598:16)
at __webpack_require__ (webpack/bootstrap:25:0)
I understand that Full Calendar does not support SSR. So as per the Gridsome documentation (https://gridsome.org/docs/assets-scripts/#without-ssr-support) I did this to import the component:
I created an alias for it's dependencies in gridsome.config.js like so:
var path = require('path');
api.configureWebpack({
resolve: {
alias: {
"timeGridPlugin": path.resolve('node_modules', '#fullcalendar/timegrid'),
etc....
}
},
})
and required those plugins in the mounted() lifecycle hook:
mounted() {
if (!process.isClient) return
let timeGridPlugin = require('timeGridPlugin')
...
},
components: {
FullCalendar: () =>
import ('#fullcalendar/vue')
.then(m => m.FullCalendar)
.catch(),
}
I then wrapped the FullCalendar component in:
<ClientOnly>
<FullCalendar></FullCalendar>
</ClientOnly>
The extra dependencies required in the mounted() hook are included no problem.
However I now get the following error:
TypeError: Cannot read property '__esModule' of undefined
It seems that components() is failing to import the '#fullcalendar/vue' component.
Am I doing something wrong when importing the '#fullcalendar/vue' component?
Is there another way to include both the '#fullcalendar/vue' component and the plugin dependencies with no SSR?
Requiring the full calendar vue component in main.js by checking the gridsome client API and registering the component globally in vue seems to work and does what I expected:
// Include no SSR
if (process.isClient) {
const FullCalendar = require("#fullcalendar/vue").default
Vue.component("full-calendar", FullCalendar)
}
I also was not pointing to the default object when requiring the other modules in the component:
mounted() {
if (!process.isClient) return
let timeGridPlugin = require('timeGridPlugin').default
...
}

Getting [Vue warn]: Unknown custom element: <b-modal> even though bootstrap-vue is registered

A BootstrapVue b-modal component in a custom Vue component loads correctly in the browser. However, when testing using mocha+mochapack, it generates a Vue warning that the b-modal element is not registered. The test is using a localVue object that has BootstrapVue registered. All other bootstrap custom elements seem to be loading correctly, and do not generate any warnings.
I tried various things, including importing BModal from 'bootstrap-vue' and registering it as a component directly, but still got the same error.
import {mount, createLocalVue} from "#vue/test-utils"
import MyCustomModal from '../js/MyCustomModal';
const localVue = createLocalVue();
import BootstrapVue from 'bootstrap-vue'
localVue.use(BootstrapVue);
describe('MyCustomModal', () => {
let wrapper = mount(MyCustomModal,{
localVue
});
it('the content is "this is the content"', () => {
expect(wrapper.find(".modal-content").text()).toEqual('this is the content');
});
});
The custom Vue component:
<template>
<b-modal>
<div class="modal-content">this is the content</div>
<b-form>
my form
</b-form>
</b-modal>
</template>
<script>
export default {
data(){
return {};
}
}
</script>
The tests run correctly and pass, but it outputs the Vue warning for the b-modal element. It doesn't output the warning for b-form.
If only shallowMount not work.
You can try stub your bootstrap's components individually.
Like this:
import {shallowMount} from "#vue/test-utils";
import { BModal, BForm } from 'bootstrap-vue';
import MyCustomModal from '../js/MyCustomModal';
describe('MyCustomModal', () => {
let wrapper = shallowMount(MyCustomModal,{
stubs: {
"b-modal": BModal,
"b-form": BForm
}
});
it('the content is "this is the content"', () => {
expect(wrapper.find(".modal-content").text()).toEqual('this is the content');
});
});
You need to set the attachToDocument: true flag when you mount b-modal (or your test component/app). It needs reference to the document/body in order for it to open (needs to add classes, etc to <body> as well as a few listeners.
import Vue from 'vue';
import {mount} from "#vue/test-utils"
import MyCustomModal from '../js/MyCustomModal';
import BootstrapVue from 'bootstrap-vue'
Vue.use(BootstrapVue);
describe('MyCustomModal', () => {
let wrapper = mount(MyCustomModal);
it('the content is "this is the content"', () => {
expect(wrapper.find(".modal-content").text()).toEqual('this is the content');
});
});
Try that.