Making global plugin that I can use anywhere in app - vue.js

I have this class for sockets. Is there any way that I could make this globally accessible? I'd like to access the functions anywhere in my app for example like $socket.methodName()
What I've tried
class InitSocket {
constructor(options) {
this.options = options;
}
connect() {
console.log(this.options);
}
}
export default {
install: (Vue, options) => {
Vue.prototype.$socket = new InitSocket(options);
},
};
in main.js
const { createApp } = require('vue');
import App from "./App.vue";
import Sockets from './plugins/Socket'
const app = createApp(App);
app.use(Sockets , "test");
app.mount("#app");
But I am getting this message
Cannot set properties of undefined (setting '$socket') - What am I doing wrong?

In Vue 3 you can have multiple apps and you can no longer add to Vue prototype.
In order to write and use a plugin, follow the steps:
Step 1: Create the plugin
export default {
install: (app, options) => {
class InitSocket {
constructor(options) {
this.options = options;
}
connect() {
console.log(this.options);
}
}
// inject a globally available $socket() method
app.config.globalProperties.$socket = new InitSocket(options)
}
}
Step 2: Import and install it in main.js
import { createApp } from 'vue'
import App from "./App.vue";
import Sockets from './plugins/Socket'
const app = createApp(App);
app.use(Sockets , "test");
app.mount("#app");
Read more on the Vue docs: Plugins

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.

Set global variables from another js file in vue 3

Folder structure
main.js
/test/index.js
main.js file
import { createApp } from 'vue'
const app = createApp(App);
//the rest of code
app.config.globalProperties.$apple = "apple value";
app.config.globalProperties.$orange = "orangevalue";
/test/index.js file
app.config.globalProperties.$testvalue = "123";
How to set the global variable in /test/index.js in vue3
In /test/index.js define a plugin with this content :
export default {
install: (app) => {
app.config.globalProperties.$testvalue = "123";
}
}
then in main.js use it in this way app.use(testPlugin):
import { createApp } from 'vue'
import testPlugin from './test'
const app = createApp(App);
//the rest of code
app.config.globalProperties.$apple = "apple value";
app.config.globalProperties.$orange = "orangevalue";
app.use(testPlugin)

using Nuxt 3 with Nest

Currently we are able to build nuxt as following. But are unable to handle routes. We basically want to serve nuxt app from Nestjs.
import { NestFactory } from '#nestjs/core';
import { AppModule } from './app.module.js';
import { loadNuxt } from 'nuxt3';
import { buildNuxt, Resolver } from '#nuxt/kit';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// Check if we need to run Nuxt in development mode
const isDev = process.env.NODE_ENV !== 'production'
// Get a ready to use Nuxt instance
const nuxt = await loadNuxt({ rootDir: 'src/client-app/' })
// Enable live build & reloading on dev
if (isDev) {
buildNuxt(nuxt)
}
await app.listen(3001);
}
bootstrap();
Following is next (react) equivalent code which is working and trying to achieve in Nuxt 3.
https://github.com/hnviradiya/contact-list/blob/e38a72167d5710fcc9f3ed9718fa9bfe8ebb7d00/src/server/client-app/client-app.service.ts#L25
import { Injectable } from '#nestjs/common';
import { ConfigService } from '#nestjs/config';
import { IncomingMessage, ServerResponse } from 'http';
import createServer, { NextServer } from 'next/dist/server/next';
#Injectable()
export class ClientAppService {
private nextServer: NextServer;
constructor(private configService: ConfigService) {}
async onModuleInit(): Promise<void> {
try {
this.nextServer = createServer({
dev: this.configService.get<string>('NODE_ENV') !== 'production',
dir: './src/client',
});
await this.nextServer.prepare();
} catch (error) {
console.error(error);
}
}
handler(req: IncomingMessage, res: ServerResponse) {
return this.nextServer.getRequestHandler()(req, res);
}
}
In nuxt 2 there were nuxt.render(req, res) or nuxt.renderRoute(route, context). But these methods are not available in nuxt3.
https://nuxtjs.org/docs/internals-glossary/nuxt/
So how to serve nuxt app through NestJs.
Following is the repo where nuxt 3 code is there but it is not serving nuxt app.
https://github.com/hnviradiya/nest-nuxt
while Nestjs is a great server, it's angular style #decorators and modular setup is too unlike Nuxt3's scaffold simplicity.
This conception feels like a bad idea.

Access Nuxt custom plugin from Composition API

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');
}

Vue I18n - TypeError: Cannot redefine property: $i18n

So I'm getting kind of crazy with this. I really don't understand.
This is a minimal version of my app.js file:
import Vue from 'vue'
import VueI18n from 'vue-i18n'
console.log("vue.prototype", Vue.prototype.$i18n)
Vue.use(VueI18n)
console.log("vue.prototype", Vue.prototype.$i18n)
const createApp = function() {
// create store and router instances
const store = createStore()
const router = createRouter()
if(process.browser) {
if(window.__INITIAL_STATE__) {
store.replaceState(window.__INITIAL_STATE__)
}
}
// sync the router with the vuex store.
// this registers `store.state.route`
sync(store, router)
// create the app instance.
// here we inject the router, store and ssr context to all child components,
// making them available everywhere as `this.$router` and `this.$store`.
//
const app = new Vue({
router,
store,
render: h => h(Application)
})
// expose the app, the router and the store.
// note we are not mounting the app here, since bootstrapping will be
// different depending on whether we are in a browser or on the server.
return { app, router, store }
}
export { createApp }
As you can see I did nothing but adding Vue.use(VueI18n) to the code.
I'm using:
{
"vue-i18n": "^7.6.0"
}
Now I'm getting this error:
TypeError: Cannot redefine property: $i18n
The line where this errors appear is this function in the source code:
function install (_Vue) {
Vue = _Vue;
var version = (Vue.version && Number(Vue.version.split('.')[0])) || -1;
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && install.installed) {
warn('already installed.');
return
}
install.installed = true;
/* istanbul ignore if */
if (process.env.NODE_ENV !== 'production' && version < 2) {
warn(("vue-i18n (" + (install.version) + ") need to use Vue 2.0 or later (Vue: " + (Vue.version) + ")."));
return
}
console.log("VUE:PROTOTYPE", Vue.prototype.$i18n)
Object.defineProperty(Vue.prototype, '$i18n', {
get: function get () { return this._i18n }
});
console.log("VUE:PROTOTYPE", Vue.prototype.$i18n)
extend(Vue);
Vue.mixin(mixin);
Vue.directive('t', { bind: bind, update: update });
Vue.component(component.name, component);
// use object-based merge strategy
var strats = Vue.config.optionMergeStrategies;
strats.i18n = strats.methods;
}
Both console.log("VUE:PROTOTYPE") where added by me, and surprise, the first one returns "undefined" and the second one is never reached because of the error.
What is happening? Anybody got a clue?