I'm brand new to Vue. The documentation says that the "setup" composition API is likely to be the one supported in the future so I'm trying to use that form everywhere.
I want to use a plugin, but I can't work out how to get access to it in the setup API format.
Here is the supplied example of how to do it in Composition API:
const authCode = await this.$gAuth.getAuthCode();
When I try to use the plugin in setup form of composition API then I get an error "Cannot read properties of undefined (reading '$gAuth') "
The LOC that is producing that error looks like this:
<script setup lang="ts">
... stuff ...
const googleUser = await this.$gAuth.signIn();
My main.ts looks like this:
import gAuthPlugin from "vue3-google-oauth2";
app.use(gAuthPlugin , {
clientId: "768834812579-ivi0oopbkqe05cg6t41p83t7gteekut6.apps.googleusercontent.com",
scope: "email",
prompt: "consent",
fetch_basic_profile: false,
});
I can see that the plugin is defining a global property (here), which the Vue documentation says can be accessed on any component instance inside the application.
But the documentation only shows an example for composition (without setup) and I can't work out the syntax for this. It's quite similar to the problem raised in the comment to this downvoted answer (the actual answer didn't help me there).
Related
in my complex Vue project I am getting this console warning:
[Vue warn]: Avoid app logic that relies on enumerating keys on a component instance. The keys will be empty in production mode to avoid performance overhead.
Unfortunately I can not find the reason for this warning just by the above message.
How can I track down the reason for this warning?
Check if your watching an entire route object anywhere in your code. Doing so throws that error (in my case).
Refer this vue documentation on watching routes
Accessing router and current route inside setup
The route object is a reactive object, so any of its properties can be watched and you should avoid watching the whole route object. In most scenarios, you should directly watch the param you are expecting to change.
Was able to fix this with the suggestion done by Glass Cannon.(https://stackoverflow.com/a/70205284/11787139)
To clarify and maybe help someone else: I was trying to send an Axios request to the server of which the data I sent through was composed of a direct component reference emitted by the component function.
Component
saveItem(){
this.saved = true;
setTimeout( this.resetState, 2500);
this.$emit('saveitem', this)
},
Parent
saveitem(e){
const data = {item : e}
axios.post(target, data, {headers . . .).then((response) => {}
})
The error disappeared when I instead fetched the index of the list item by doing so:
saveitem(e){
let item;
this.items.forEach( function(item, index, array) {
if(item.id == e.id) pointer = item
})
data.item = pointer
axios.post(target, data, {headers . . .).then((response) => {}
})
}
So I was also having this issue, but not for the reasons the accepted answer provided. It was occurring due to my Vuex store. After a lot of digging I discovered the cause was the presence of the "CreateLogger" plugin.
So if you're having this issue and it's not due to you watching an entire route, check if you're using the CreateLogger plugin in Vuex. That might be the culprit.
This happens for me when I pass this to a data object
data() {
return {
updateController: new UpdateController({
reportTo: this
})
}
}
This used to work fine with Vue 2 but causes this error in Vue 3.
Making this modification solved the problem for me.
data() {
return {
updateController: new UpdateController({
reportTo: () => this
})
}
}
I know this might be anti-pattern but I needed to inject partial reactivity to a non-reactive part of a JS library and this was the most not complicated way of achieving this that I can think of.
This happens to me when destructuring a ref without .value.
This was happening to me only in Firefox, and when I removed the Vue Dev Tools extension it stopped. After re-installing Vue dev tools it hasn't come back. Make sure you have the latest version of the Vue Dev Tools for your browser.
I would like to create a viewer PDF files into electron/vuejs application.
I need to use the pdfjs librarie.
For that I installed this package : "pdfjs-dist": "2.6.347"
and in my component vuejs I try to used this by doing this :
import pdfjsLib from "pdfjs-dist/webpack";
This import instruction seeems to be running good. But If a start used this like this :
created()
{
pdfjsLib.getDocument()
}
I throw this error :
Cannot read property 'getDocument' of undefined"
I try lot of tricks but I don't find any solution for use this library in my component.
Anyone have a vuejs project with pdfjslib for viewing pdf ?
This seems to work:
import("pdfjs-dist").then((pdfjsLib) => {
pdfjsLib.getDocument();
});
It can be used inside either created() or mounted(). I'd personally use it in mounted.
Working demo here.
Also note calling getDocument() with no arguments seems to trigger some lib error (but that's outside the scope of current question):
Invalid parameter in getDocument, need either Uint8Array, string or a parameter object
I'm trying to use the google maps API at my vue2 project and I have tried some ways that have failed. After using the vue2googlemaps module and the node module from google I have decided to use the CDN directly and add it to the index page. My problem now is that to acced to the google object, for example, to create a Marker or something like that, I need to use this.marker = new window.google.maps.Marker() for example, but in the tutorials I have seen, everyone uses directly the google object and never uses that window. I can`t understand why it happens. It would be appreciated if someone shows me the correct way to import or use this library on google.
It's because your template's code is compiled and executed in your component instance (a.k.a vm) 's scope, not in the global (a.k.a. window) scope.
To use google directly in your template you could add the following computed:
computed: {
google: () => window.google
}
If your problem is not having google defined in the component's <script>, a simple solution is to add it as a const at the top:
import Vue from 'vue';
const google = window.google;
export default Vue.extend({
computed: {
google: () => google // also make it available in template, as `google`
}
})
An even more elegant solution is to teach webpack to get google from the window object whenever it's imported in any of your components:
vue.config.js:
module.exports = {
configureWebpack: {
externals: {
google: 'window.google'
}
}
}
This creates a google namespace in your webpack configuration so you can import from it in any of your components:
import google from 'google';
//...
computed: {
google: () => google // provide it to template, as `google`
}
Why do I say it's more elegant?
Because it decouples the component from the context and now you don't need to modify the component when used in different contexts (i.e: in a testing environment, which might not even use a browser, so it might not have a window object, but a global instead; all you'd have to do in this case is to define a google namespace in that environment and that's where your component will get its google object from; but you wouldn't have to tweak or mock any of the component's methods/properties).
I feel like this is a really stupid question and I'm missing something really obvious but I'll ask anyway.
I have a Nuxt plugin that injects a function into the Vue instance, but I need to access another injected method (which is injected by a module, buefy) from within my method. Here's the plugin:
import Vue from 'vue'
Vue.prototype.$disp_error = (err) => {
console.error(err)
Vue.$snackbar.open({
duration: 60000,
message: 'Uh oh! Something went wrong. If it keeps happening, please contact us with this error: ' + err.toString(),
type: 'is-danger'
})
}
However it says $snackbar is undefined. I guess I could solve it by using this as a second argument when I call this.$disp_error within my components, and then using the this context to call $snackbar in my method, but I don't really want to use add second argument.
Could someone remind me what I'm missing? Thanks.
In my Vuex setup, the store is currently structured like this:
store
- modules
- common_data
- index.js
- mutations.js
- actions.js
- getters.js
Now, one of the actions inside actions.js is defined as:
populateTimeZones(context) {
var baseUrl = context.getters.getApiBaseUrl;
this.$http.get(baseUrl + '/time-zones')
.then(function (res){
if(res.status == 'ok'){
this.$store.commit('SET_TIME_ZONES', res.info.timeZones);
} else {
alert('An error occurred. Please try again!');
return;
}
}.bind(this));
}
I think the Vue instance is not available here, which is causing the action to fail with the error: Cannot read property 'get' of undefined. I've tried other combinations like this.axios and vue.axios but the result is same.
Am I doing something wrong? What is the common pattern for handling such cases?
You won't be able to access the Vue instance without passing it through or creating a new one.
A simple way to do what you want is to simply pass your this through to your action this.$store.dispatch('populateTimeZones', this), then change your method signiture to populateTimeZones({ context }, vueInstance). This would then allow you to access vueInstance.$http.
Another idea would be something called vue-inject which is a DI container for Vue. It would allow you to register axios as a service and then simply call VueInjector.get('axios') whenever you need it. On the Vue component itself you can do dependencies: ['axios'] and then use like this.axios. Not so much an issue in this case but helpful when you have lots of services doing work for you