is it available to call the methods where in the vue component from the plugin? - vue.js

I wanted to access the vue.data or methods in the plugin.
no matter what I tried several times, it didn't work.
such as eventBus, Mixin etc...
so I'm curious about the possibility to call the methods like that.
thank you for reading this question.
here is the custom component.
<template>
<div>
<v-overlay :value="isProcessing">
<v-progress-circular indeterminate size="64"></v-progress-circular>
</v-overlay>
</div>
</template>
<script lang="ts">
import { Component, Vue } from 'vue-property-decorator';
#Component
export default class ProgressCircular extends Vue {
private isProcessing: boolean;
startProcess() {
this.isProcessing = true;
}
}
</script>
and this is the plugin source.
import ProgressCircular from '#/components/ProgressCircular.vue';
import { VueConstructor } from 'vue';
import Vuetify from 'vuetify/lib';
import vuetify from './vuetify';
export default {
install(Vue: VueConstructor, options: any = {}) {
Vue.use(Vuetify);
options.vuetify = vuetify;
Vue.component('progress-circular', ProgressCircular);
Vue.prototype.$fireProgressing = function () {
// it didn't work
// I just wanted to access the method where in the Vue Component
// ProgressCircular.startProcess();
};
},
};

use the plugin syntax to extend vue like:
Vue.use({
install: Vue => {
Vue.prototype.$fireProgressing = () => {
};
}
});
or
Vue.use(YOURPLUGIN);
before you mount vue

Related

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>

How to test a Vuex module action is called in Vue component mounted function?

I have a Vue component like this...
<template>
<div class="mapdiv"></div>
</template>
<script lang="ts">
import Vue from "vue";
import Component from "vue-class-component";
import { mapViewModule } from "#/store/modules/MapViewModule";
#Component
export default class GeospatialMap extends Vue {
async mounted(): Promise<void> {
mapViewModule.initializeMapView(this.$el as HTMLDivElement);
}
}
</script>
<style scoped>
.mapdiv {
height: 700px;
width: 1000px;
}
</style>
...and I am trying to test that the mapViewModule.initalizeMapView function gets called, which is an action in my Vuex module.
I am using Jest and have looked to other answers such as: https://stackoverflow.com/a/66987942/2052752 but have had no luck....
import { shallowMount, createLocalVue } from "#vue/test-utils";
import Vuex from "vuex";
import GeospatialMap from "#/components/Geospatial.vue";
describe("GeospatialMap - ", () => {
const localVue = createLocalVue();
localVue.use(Vuex);
const modules = {
mapViewModule: {
state: {},
actions: {
initializeMapView: jest.fn()
},
namespaced: true
}
};
const store = new Vuex.Store({ modules });
shallowMount(GeospatialMap, { localVue, store });
it("when component created, initializes the map view", async () => {
expect(modules.mapViewModule.actions.initializeMapView).toHaveBeenCalled();
});
});
Simply put...the jest.fn says its not called in the console..
expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
I'm not sure where it is going wrong. Am I not mocking the module action right?
I just want to test that the Vuex action gets called when this component is initialized.
Yep, you are not mocking the store right. And I also would like to say, that you are using the store in a little strange way but it is up to you.
I made some changes to component to make the decision of your problem as clear as possible.
<template>
<div class="mapdiv">
I am
</div>
</template>
<script lang="ts">
import Vue from 'vue'
import Component from 'vue-class-component'
import { mapViewModule } from '#/helpers/someModule' // there you put your path to the module
#Component
export default class GeospatialMap extends Vue {
mounted (): void {
mapViewModule.initializeMapView(this.$el as HTMLDivElement)
}
}
</script>
<style scoped>
.mapdiv {
height: 700px;
width: 1000px;
}
</style>
When your are calling mapViewModule.initializeMapView in mount hook you are just using simple js-function so I tried to mock that call by creating __mock__ folder in #/helpers/ with someModule.ts file in it with the code below:
// #/helpers/__mock__/someModule.ts
export const mapViewModule = {
initializeMapView: jest.fn((el: HTMLDivElement) => console.log('I am MOCK!!!', el))
}
Then in spec-file we must tell Jest to use our mock-file instead of real file like that:
import { shallowMount, Wrapper } from '#vue/test-utils'
import GeospatiaMap from '#/components/GeospatiaMap/GeospatiaMap.vue'
import { mapViewModule } from '#/helpers/someModule'
jest.mock('../../helpers/someModule.ts') // there you put your path to module you want to mock
let wrapper: Wrapper<GeospatiaMap & { [key: string]: any }>
describe('GeospatiaMap.vue', () => {
test('initializeMapView was called', () => {
wrapper = shallowMount(GeospatiaMap) // wrapper property is useless now but you can use it your future tests
expect(mapViewModule.initializeMapView).toBeCalled()
})
})
That's it. Hope that'd help.

Vue global component not defined

I am creating a Vue plugin that adds a custom component to the global scope like so:
import CustomComponent from './CustomComponent.vue';
const MyPlugin = {
install(Vue, options) {
Vue.component('CustomComponent', CustomComponent);
}
}
and the component itself is simply:
<template>
<h1>Hi from the custom component</h1>
</template>
<script>
export default {
name: 'CustomComponent',
mounted() {
console.log('hello console');
}
}
</script>
And then finally I import the plugin into my main.js file (I'm using Gridsome):
export default function (Vue, { router, head, isClient }) {
Vue.use(MyPlugin);
}
But now I expect that when I make a component I can extend the CustomComponent since it's in the global scope like so:
<template>
<h2>Hi again</h2>
</template>
<script>
export default {
name: 'RegularComponent',
extends: CustomComponent
}
</script>
But this gives me an error of Custom Component not defined and it seems like it's because CustomComponent isn't in the global scope because if I import the CustomComponent vue file in my RegularComponent vue file it works. However, this is not the behavior I would like and I cannot figure out why CustomComponent is not just globally available.
CustomComponent is a javascript object, you still need to import to use it
<script>
import CustomComponent from './CustomComponent.vue'
export default {
name: 'RegularComponent',
extends: CustomComponent
}
</script>
I think when define component as global, that means you can use it in template without re-declare:
<template>
<h2>Hi again</h2>
<custom-component />
</template>

How to test this component?

I have a Page level component which implements a component BookingInformation with slots. In the Page component, it's got another component BookingInformationHeader with slots. header and default.
My question is, how should I set up my test so that I can test that the GoogleConversionTrackingImage is visible when #Reservation.State wasBookingJustMade changes to true?
<script lang="ts">
import { Vue, Component } from "vue-property-decorator";
import { Reservation } from "#/store/vuex-decorators";
import { BookingInformation, BookingInformationHeader } from "#/components";
import GoogleConversionTrackingImage from './components/GoogleConversionTrackingImage.vue';
#Component({
components: {
BookingInformation,
BookingInformationHeader,
GoogleConversionTrackingImage
}
})
export default class ConfirmationPage extends Vue {
renderTrackingImage: boolean = false;
#Reservation.State wasBookingJustMade: boolean;
}
</script>
<template>
<booking-information page-type="confirmation-page" class="confirmation-page">
<template slot="header" slot-scope="bookingInfo">
<booking-information-header>
<template slot="buttons">
// some buttons
</template>
</booking-information-header>
<google-conversion-tracking-image v-if="wasBookingJustMade" />
</template>
</booking-information>
</template>
By using vue test utils https://vue-test-utils.vuejs.org/ and chai https://www.chaijs.com/ in your test file you can do something like:
import mount from "#vue/test-utils";
import expect from "chai";
const wrapper = mount(BookingInformation,<inner components you want to test>);
expect(googleImage.exists()).to.be.true;
wrapper.setData({
wasBookingJustMade: true,
});
const googleImage = wrapper.find("google-conversion-tracking-image");
expect(googleImage.exists()).to.be.false;
You'll probably need to import the page level component as well.
You can give an id to the component you want to find and then search by id.

Make event handlers I need accessible method

In laravel 5.7 / vue 2.5.17 / vuex^3.1.0 I make event handlers in my container file MainApp.vue
with events:
mounted() {
bus.$on('dialog_confirmed', (paramsArray) => {
alert( "dialog_confirmed paramsArray::"+var_dump(paramsArray) )
if ( paramsArray.key == this.addToBookmarksKey(paramsArray.hostel_id) ) {
this.runAddToBookmarks(paramsArray.hostel_id, paramsArray.index);
}
if ( paramsArray.key == this.deleteFromBookmarksKey(paramsArray.hostel_id) ) {
this.runDeleteFromBookmarks(paramsArray.hostel_id, paramsArray.index);
}
})
}, // mounted() {
The idea is that runAddToBookmarks must be called from different pages and I need to set common method check which event is triggered.
I tried in resources/js/helpers/commonFuncs.js to add method :
export function addToBookmarksKey(hostel_id) {
return 'hostels_sorted__add_to_bookmarks_'+hostel_id;
}
and to use it in my vue file. like:
...
<template v-if="hostelsList.length">
<template v-for="nextHostel, index in hostelsList" >
<hostel-list-item
:currentLoggedUser="currentLoggedUser"
:nextHostel="nextHostel"
:index="index"
:hostelBookmarks="hostelBookmarks"
:delete_from_bookmarks_key="deleteFromBookmarksKey(nextHostel.id)"
:add_to_bookmarks_key="addToBookmarksKey(nextHostel.id)"
></hostel-list-item>
</template>
</template>
...
</template>
<script>
import {bus} from '../../../app';
import appMixin from '../../../appMixin';
import { addToBookmarksKey } from "../../../helpers/commonFuncs";
But I got error : property or method "addToBookmarksKey" is not defined on the instance but referenced during render.
Why addToBookmarksKey is not accessible in template of my vue file and which is simple way to work it?
I need to use addToBookmarksKey in many vue files , both in template and it javascript block ?
Thanks!
You need to define your helper function inside your component instance to use it within the template:
<script>
import { addToBookmarksKey } from "../../../helpers/commonFuncs";
export default {
//...
methods: {
addToBookmarksKey,
//...
}
}
You also can define it globally by adding the function in a mixin directly in main.js:
import Vue from "vue";
import App from "./App.vue";
import { addToBookmarksKey } from "path/to/the/helpers/commonFuncs";
Vue.mixin({
methods: {
addToBookmarksKey
}
})
new Vue({
render: h => h(App)
}).$mount("#app");
no need to import and define it inside your components this way.