Access Nuxt custom plugin from Composition API - vue.js

I am using VueClipboard in my nuxt project.
https://www.npmjs.com/package/vue-clipboard2
I have a plugin file vue-clipboard.js
import Vue from "vue";
import VueClipboard from 'vue-clipboard2';
Vue.use(VueClipboard);
It is imported into nuxt.config
plugins: ['#/plugins/vue-clipboard'],
This sets up a global variable $copyText and in nuxt without the composition API I can do something like
methods: {
async onCopyCodeToClipboard() {
const code = 'code'
await this.$copyText(code)
},
},
However inside the setup using the composition API (#nuxtjs/composition-api) when I write a function I do not have access to this.$copyText
const onCopyCodeToClipboard = async () => {
const code = context.slots.default()[0].elm.outerHTML
// -> Can't use this here - await this.$copyText(code)
}
So how do I make $copyText available to use inside the composition API?

I was able to get this to work via the Nuxt useContext() method:
import { useContext } from '#nuxtjs/composition-api'
export default function () {
const { $copyText } = useContext();
$copyText('code');
}

Related

Vue 3 get current application instance

How to access to current instance of application inside a component?
Option 1: Create a plugin
// define a plugin
const key = "__CURRENT_APP__"
export const ProvideAppPlugin = {
install(app, options) {
app.provide(key, app)
}
}
export function useCurrentApp() {
return inject(key)
}
// when create app use the plugin
createApp().use(ProvideAppPlugin)
// get app instance in Component.vue
const app = useCurrentApp()
return () => h(app.version)
Option 2: use the internal api getCurrentInstance
import { getCurrentInstance } from "vue"
export function useCurrentApp() {
return getCurrentInstance().appContext.app
}
// in Component.vue
const app = useCurrentApp()
In Vue.js version 3, you can access the current instance of an application inside a component using the getCurrentInstance() function provided by the Composition API.
Here's an example:
import { getCurrentInstance } from 'vue'
export default {
mounted() {
const app = getCurrentInstance()
console.log(app.appContext.app) // This will log the current instance of the application
}
}
Note that getCurrentInstance() should only be used in very specific situations where it's necessary to access the instance. In general, it's recommended to use the Composition API's reactive properties and methods to manage state and actions inside a component.

How to access Vuex map helpers with Composition API

I am using Composition API in Vue2. Can you tell me how to access mapState with composition API? I want to watch for state changes as well. Hence I would have to use it within setup function as well (not only in return). Thanks
The Vuex map helpers aren't supported (yet?) in the Vue 2 or Vue 3 composition API, and this proposal for them has been stalled for a while.
You'll have to manually create a computed like in the docs:
const item = computed(() => store.state.item);
A more complete example:
import { computed } from 'vue';
import { useStore } from 'vuex';
export default {
setup() {
const store = useStore();
const item = computed(() => store.state.item);
return {
item
};
}
}
For me the trick was using the vuex-composition-helper npm package.
https://www.npmjs.com/package/vuex-composition-helpers
import { useState, useActions } from 'vuex-composition-helpers';
export default {
props: {
articleId: String
},
setup(props) {
const { fetch } = useActions(['fetch']);
const { article, comments } = useState(['article', 'comments']);
fetch(props.articleId); // dispatch the "fetch" action
return {
// both are computed compositions for to the store
article,
comments
}
}
}

How to mock modules in storybook's stories?

I have a Vue component which includes some external modules with complicated logic. For example:
// Component.vue
import Vue from 'vue';
import { externalModule } from '#/path/to/module';
export default {
methods: {
useExternalModule() {
externalModule.doSomethig();
}
}
};
Is it possible to mock the externalModule inside the story?
I'm using Storybook v6.
You can create a __mocks__ folder to put your mock components in. Then in your .storybook/main.js file use this to point webpack to your mock file.
module.exports = {
// your Storybook configuration
webpackFinal: (config) => {
config.resolve.alias['externalModule'] = require.resolve('../__mocks__/externalModule.js');
return config;
},
};
This is covered in the docs under "Mocking imports".
However, this is a global configuration and not a story level configuration.

Understanding context and app methods in NUXT

I am trying to use bugsnagClient and its notify method in plugins/axios.js I have this code in plugins/bugsnag.js
import Vue from "vue"
import bugsnag from "#bugsnag/js"
import bugsnagVue from "#bugsnag/plugin-vue"
// const bugsnagClient = bugsnag(`${process.env.BUGSNAG_API_KEY}`)
var bugsnagClient = bugsnag({
apiKey: "",
notifyReleaseStages: ["production"]
})
bugsnagClient.use(bugsnagVue, Vue)
I want to attach a method to app or context as
export default ({ app }, inject) => {
function bugsnagNotify(error) {
return bugsnagClient.notify(new Error(error))
}
// Set the function directly on the context.app object
app.bugsnagNotify = bugsnagNotify
}
And I want to use it in plugins/axios.js
export default function({ store, app }) {
if (store.getters.token) {
console.log(app.bugsnagNotify("ss"))
app.$axios.setToken(store.getters.token, "Bearer")
} else {
//app.$bugsnag.notify(new Error("Bearer tooken is missing in Axios request."))
}
}
In this file, when I do console.log for just app
I can see bugsnagNotify: ƒ bugsnagNotify(error)
but when I call app.bugsnagNotify("error") I only get error such as VM73165:37 TypeError: app.bugsnagNotify is not a function
I have also tried this in plugins/bugsnag.js
export default (ctx, inject) => {
inject('bugsnag', bugsnagClient)
}
I only get an error as
app.$bugsnag.notify(new Error("Bearer tooken is missing in Axios request."))
If you are injecting into context inside one plugin and want to use that function inside another, you need to make sure that the plugin in which you are injecting comes first inside nuxt.config.js
...
plugins: [
'~/plugins/bugsnag.js',
'~/plugins/axios.js'
],
...

Not able to access i18 plugin from mutation in classic mode store in Nuxt application

I'm trying to implement Vuex i18n package within my Nuxt application. In my nuxt.conf.js file in plugins array I have:
{
src: '#/plugins/i18n.js',
ssr: false
},
plugins/i18n.js file is:
import Vue from "vue";
import vuexI18n from "vuex-i18n/dist/vuex-i18n.umd.js";
import toEnglish from "../translations/toEnglish";
import toSpanish from "./../translations/toSpanish";
import toGerman from "./../translations/toGerman";
export default ({ store }) => {
Vue.use(
vuexI18n.plugin,
store,
{
onTranslationNotFound: function (locale, key) {
console.warn(`vuex-i18n :: Key '${key}' not found for locale '${locale}'`)
}
}
);
// register the locales
Vue.i18n.add('en', toEnglish);
Vue.i18n.add('de', toGerman);
Vue.i18n.add('es', toSpanish);
// Set the start locale to use
Vue.i18n.set('de');
Vue.i18n.fallback('en');
}
Last thing is my store. I'm using classic mode of vuex store in Nuxt:
import Vuex from "vuex";
const store = () => {
return new Vuex.Store({
state: () => ({
currentLanguage: ''
}),
mutations: {
changeLang(state, response) {
if (response) {
console.log(this);
state.currentLanguage = response;
this.i18n.set(response);
}
}
}
})
};
export default store;
As you can see in store file in mutation I'm trying to access i18n plugin with this keyword. Unfortunetally in print error in console:
TypeError: Cannot read property 'set' of undefined
this which I consoled also inside mutation is:
I changed this.i18n.set(response); to state.i18n.locale = response; inside my mutation and now it seems working.
For some reason when I call this mutation my video.js player refresh. I will try to find out why.