I'm trying to create a global helper function via Vue mixin on a Laravel Inertia project to no avail:
//app.js
Vue.mixin({
methods: {
myFunction() {
return 'Returnign from myFunction';
},
},
});
new Vue({
...
}).$mount(app);
.
//MyComponent.vue
console.log(myFunction()); // ReferenceError: myFunction is not defined
On a standalone Vue.JS project, this works. Maybe there's something behind the scene in Inertia that prevents the mixin from loading. Can somebody help me understand why this is happening?
Thank you.
you need () on your function
Vue.mixin({
methods: {
myFunction() {
return 'Returnign from myFunction';
},
},
});
and then you missed this before your mixin function
console.log(this.myFunction());
You need to add the function in the mixin of the createInertiaApp method in your app.js file.
For instance:
createInertiaApp({
resolve: (name) => require(`./Pages/${name}.vue`),
setup ({ el, app, props, plugin }) {
return createApp({ render: () => h(app, props) })
.use(plugin)
.mixin({
methods: {
myFunction: () => {
return 'Returning from myFunction';
}
}
})
.mount(el)
}
})
Related
I want to use a global mixin in vue3.
Using the mixin property - mixin:[mixinName] in createApp does not work.
Using the method .mixin(mixinName) will work.
What is the difference?
Not working:
return createApp({
mixins: [utilsMixin],
setup() {
return () => h(HelloWorld, {}, () => childComponents)
}
})
Working Version:
return createApp({
setup() {
return () => h(HelloWorld, {}, () => childComponents)
}
}).mixin(utilsMixin)
I would like to create a Nuxt plugin that automatically adds a computed to components that have a certain property (without using a mixin).
For example, any component that have a addComputedHere property:
export default {
data() {
return {}
},
computed: {
myComputed: () => 'foo'
},
addComputedHere: true
}
would turn into:
export default {
data() {
return {}
},
computed: {
myComputed: () => 'foo',
injectedComputed: () => 'bar' // Injected
},
addComputedHere: true
}
So far, I'm not sure what's the best solution among using a Nuxt plugin/module/middleware or simply a Vue Plugin (if it's feasible).
How would you do it?
If anybody is in the same case, I found a solution by creating a Vue plugin that applies a mixin to customize the component in beforeCreate:
import Vue from 'vue';
const plugin = {
install(Vue, options) {
Vue.mixin({
beforeCreate() {
if (this.$options.addComputedHere) {
this.$options.computed['injectedComputed'] = () => 'bar';
}
}
})
}
};
Vue.use(plugin);
I am using the structure below in my Vue.js web application. I am now trying to implement testing to it. But when trying to test the exampleOfFunction it says that this.exampleOfData2 is undefined.
<template>
*Some HTML*
</template>
<script>
*Some Imports*
export default {
data() {
return {
exampleOfData1: [],
exampleOfData2: 100
},
methods: {
exampleOfFunction:function(){
if(this.exampleOfData2 === 100)
{
return false;
}
return true;
},
created() {
},
mounted() {
}
}
</script>
In my testfile I then try to access the code above and I succeed with console.log(FileToTest.data()); I can see the values of data and I can access the function with FileToTest.methods.exampleOfFunction(); but when I call the function it says that this.exampleOfData2 is undefined.
It looks like you're using the component options definition instead of the component instance in your tests.
You should be creating a wrapper by mounting the component, and then you could access the component method via wrapper.vm:
import { shallowMount } from '#vue/test-utils'
import FileToTest from '#/components/FileToTest.vue'
describe('FileToTest', () => {
it('exampleOfFunction returns false by default', () => {
const wrapper = shallowMount(FileToTest)
expect(wrapper.vm.exampleOfFunction()).toBe(false)
})
it('exampleOfFunction returns true when data is not 100', () => {
const wrapper = shallowMount(FileToTest)
wrapper.setData({ exampleOfData2: 0 })
expect(wrapper.vm.exampleOfFunction()).toBe(true)
})
})
I'm adding JWT authentication to my Vue app and I have my Login.vue and App.vue seperated which means that I don't want to render the App.vue when the user is not logged in.
new Vue({
router,
render: function (app) {
if (this.$auth.check()) {
return app(App);
} else {
return app(Login);
}
}
}).$mount('#app')
This works but since
this.$auth.check()
Takes a second to load you see the Login app being rendered for a second and then it switches to the App. How can I fix this? I think I should use await but I can't get it to work properly.
How can I fix this? I think I should use await but I can't get it to work properly.
It depends on what is this.$auth.check() return. If it returns a promise, the answer is yes you should use await.
But unfortunately render function must be synchronous. What you can do is use one more wrapper component.
new Vue({
render(createElement) {
return createElement({
data: () => ({
component: null
}),
async created() {
this.component = await checkAuth() ? App : Login
},
render(createElement) {
return createElement(this.component)
}
})
}
}).$mount('#app')
Demo
Note:
I would prefer to create a wrapper component as single-file component.
It seems you are using vue-router you might consider to use Navigation Guards instead.
Update
As you may be already notice you have no need a wrapper component at all.
new Vue({
data: () => ({
component: null
}),
async created() {
this.component = await checkAuth() ? App : Login
},
render(createElement) {
return createElement(this.component)
}
}).$mount('#app')
I'm trying to unit test (with vue-test-utils) a component, which has a beforeRouteUpdate in component navigation Guard like this:
<template>
...
</template>
<script>
export default {
computed: {
...
}
...
beforeRouteUpdate(to, from, next) {
// code to be tested
this.$store.dispatch('setActiveTask')
}
}
</script>
I do render the component in the test file with shallowMount and mock stuff like the $store.
beforeEach(() => {
cmp = shallowMount(Task, {
mocks: {
$store: store,
$route: {
params: {
taskID: 12,
programID: 1
}
}
},
i18n: new VueI18N({
silentTranslationWarn: true
}),
stubs: {
'default-layout': EmptySlotComponent,
'nested-router': EmptySlotComponent,
RouterLink: RouterLinkStub
}
})
})
it('has beforeRouteUpdate hook', () => {
// how do i call beforeRouteUpdate now?
// cmp.vm.beforeRouteUpdate(...)
}
Has anyone some ideas about this?
UPDATE:
I created a minimal example with #vue/cli and Mocha + Chai as unit test tools, which can be found here: https://github.com/BerniWittmann/vue-test-navigation-guard-reproduction
Got it working, but with a kind of hacky solution.
my test now looks like this:
it('test', () => {
const beforeRouteUpdate = wrapper.vm.$options.beforeRouteUpdate
const $store = {
dispatch: () => {
}
}
spyOn($store, 'dispatch').and.returnValue({ then: (arg) => arg() })
let next = jasmine.createSpy('next')
render()
beforeRouteUpdate.call({ $store }, {
params: {
taskID: 1
}
}, {}, next)
expect($store.dispatch).toHaveBeenCalledWith('setActiveTask', 1)
expect(next).toHaveBeenCalled()
})
The navigation guard is available in wrapper.vm.$options.beforeRouteUpdate, but calling this I lost the context of this so I was not able to call this.$store.dispatch in the component navigation guard, thats why I needed to use the .call() method
Following code worked fine for me for testing route navigation guards.
const beforeRouteUpdate = wrapper.vm.$options.beforeRouteUpdate[0];
let nextFun = jest.fn();
beforeRouteUpdate.call(wrapper.vm , "toObj", "fromObj", nextFun);
testing route navigation guards git hub
how to test vue router beforeupdate navigation guard