Initialize Pinia inside Vue 2 component - vue.js

Is it possible to initialize Pinia store inside Vue 2 single file component? Right now I'm trying do this:
import { createPinia, PiniaVuePlugin } from 'pinia';
import Vue from 'vue';
Vue.use(PiniaVuePlugin);
const pinia = createPinia();
Vue.prototype.$pinia = pinia;
and it works in app but when I import this component to another App I'm having this error:
getActivePinia was called with no active Pinia. Did you forget to install pinia?
Is it even possible to initialize the pinia after main instance of app is created?

Related

How can I access global variable in vue 3 outside vue component?

I defined my global variable in main.js file like this
const app = Vue.createApp({})
app.config.globalProperties.$myGlobalVariable = globalVariable***
and then when I tried to access this variable $myGlobalVariable in other js file it is undefined, but I can access in vue components.
In the vue 2 it is possible to access both in js file and vue components. I hope you gonna help me :)
In order to access a global Vue variable outside of a Vue component you have to:
1. Export the app instance
/* main.js */
export const app = Vue.createApp({})
app.config.globalProperties.$myGlobalVariable = globalVariable
2. Import the app instance in the other JS file
/* other.js */
import { app } from '#/main.js'
console.log(app.config.globalProperties.$myGlobalVariable)

VueJS 3 See all globally registered components. this.$options.components is empty

Hello I have a new Vue 3 app using Vite.
I'm registering my UserTextInput component globally but inside all my components this.$options.components is empty
import UserTextInput from "./components/defaultComponents/UserTextInput.vue";
const app = createApp(App);
app.component('UserTextInput', UserTextInput);
app.mount('#app');
Inside any other component
mounted() {
console.log(this.$options.components); // {} empty object
},
I'm looking for a way to see what components have been registered globally.
Any Ideas?
You could try this one
import { getCurrentInstance } from 'vue';
getCurrentInstance().appContext.components // this will list all component registered globally
I found the list stored here in my Vue 3 app:
app._instance.appContext.components

Transition from gobal Vue instance to app breaks import dependency

I'm looking at migrating a Vue 2 app to Vue 3 and ran into a problem. The Vue 2 app used to start with importing a whole lot of components and directives:
// these components register to the global Vue instance
import {ComponentA} from './componenta';
import {directiveA} from './directivea';
// create app (after the components are registered)
new Vue({...})
This worked fine, but when changing this code to Vue3, the app instance is now created instead. This instance isn't actually available when the global directives and components are imported.
What's the recommended way for dealing with this? I can't reorder the imports to the bottom of the file as webpack bundles them always at the top...
The order of imports does not matter in your case - what matters is the order of the JavaScript statements that follow the import section.
You should first create the app instance and only then register your global components to this instance - as explained in https://learnvue.co/2020/08/how-to-register-a-vue3-global-component/
import { createApp } from 'vue'
import PopupWindow from './components/PopupWindow'
import App from "./App.vue"
const app = createApp(App)
app.component('PopupWindow', PopupWindow) // global registration - can be used anywhere
app.mount('#app')
I settled with a solution that imports the app instance before component registration/definition (which occur within the component file) in an attempt to keep the current structure.
import {app} from './instance';
import './components/popupwindow';
import App from './app.vue';
const app = createApp(App)
app.mount('#app')
// instance.js
import {createApp} from 'vue';
const app = createApp();
export {app};
// popupwindow.vue
import {app} from '../instance';
// component registration+definition here (for global components only)
app.component('popup', {
...
}

How to access document/window from shadow dom in vue?

I am using a library (vue-airbnb-style-datepicker) which is trying to access the document object to attach some event listeners. Wrapping the vue app as a web component results into following error:
Cannot read property 'addEventListener' of null
My main.js:
import Vue from "vue";
import App from "./App.vue";
import wrap from "#vue/web-component-wrapper";
import AirbnbStyleDatepicker from "vue-airbnb-style-datepicker";
Vue.use(AirbnbStyleDatepicker, {});
Vue.config.productionTip = false;
const WrappedElement = wrap(Vue, App);
window.customElements.define("gpc-components", WrappedElement);
How can i use the document object in a web component?
Is it even possible?
If not, does a workaround exist?

How to use Axios in main.js

I am learning Vue.js.
I have this code which runs fine :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
const app = createApp(App).use(store).use(router)
app.mount('#app')
Now I would like to add some import, for example 'axios'. This code does not run :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
const app = createApp(App).use(store).use(router).use(axios)
app.mount('#app')
The error is:
Uncaught RangeError: Maximum call stack size exceeded
at merge (utils.js?c532:276)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
at assignValue (utils.js?c532:282)
at forEach (utils.js?c532:253)
at merge (utils.js?c532:291)
So how to add some other "use" in the main.js file ? It is certainly very basic but I am a beginner.
You're using vue 3 and axios is not a plugin (we cannot register it like app.use()) it's a javascript module that could be add to the app instance like :
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
import axios from 'axios'
const app = createApp(App).use(store).use(router)
app.config.globalProperties.axios=axios
app.mount('#app')
and in child component reference it like :
this.axios
Note: the code below is valid for Vue 2.x. Since version 3, some stuff has changed regarding initialization (createApp function is now required).
What I usually do in my code is the following:
import Vue from 'vue';
import axios from 'axios';
// Add it to Vue prototype (use any variable you like, preferrably prefixed with a $).
Vue.prototype.$http = axios;
// Instantiate the main vue app.
let app = new Vue({
//
});
This means that the $http object is now available in all your components using this.$http. Since it is assigned as a prototype variable, it is considered a singleton (it is re-used everywhere), so you can add any options you need to the axios variable before assigning it to Vue.prototype.$http.
Additionally:
Vue.use() is made specifically for enabling Vue plugins. That means the given parameter must use the exact syntax as described here https://v2.vuejs.org/v2/guide/plugins.html . Since axios is not a Vue plugin but just a regular JavaScript library, you cannot use it with this function.
If you want to make it especially nice (or convoluted), you can use the following syntax:
Vue.use({
install(v) {
v.prototype.$http = axios;
// Do other stuff like adding mixins etc.
}
})
This may clear up your code if you move this code to another file, so it could end up like this:
import myCustomAxiosLoader from './bootstrap/axios';
Vue.use(myCustomAxiosLoader);