Cannot use Maps JavaScript API on vue (nuxt) - vue.js

here is code that i try
head: {
script: [
{
src: "https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places&callback=initAutocomplete",
},
],
},
mounted() {
new google.maps.places.Autocomplete(
document.getElementById('autocomplete')
)
},
And i got this error
Thanks for any help

When you go to import the googlemaps scripts it is not said that the script has already been loaded.
The best thing is to put a global hook and then emit an event like maybe an eventHub.
Example of event hub https://www.digitalocean.com/community/tutorials/vuejs-global-event-bus
//your mapsPlugin.js
import eventHub from "./your-event-hub";
window.initAutocomplete = () => {
eventHub.$emit("maps-loaded");
};
mounted() {
// mounted of your component
eventHub.$on("maps-loaded", () => {
// your stuff
});
},

You can try:
Introduced in the index.html page
<script src="https://maps.googleapis.com/maps/api/js?key=MYKEY&libraries=places&callback=initAutocomplete"></script>
new google.maps.places.Autocomplete() change into new window.google.maps.places.Autocomplete();

Related

How Do I Resolve this "An error was captured in current module: TypeError: e.parse is not a function"

How do I solve this Vue Js error on Shopware 6 Administration. The module is suppose to select a column in the database table.
PS. This is the complete code. I'm trying to read data from the database and view it in the twig template.
const { Component, Mixin } = Shopware;
const { Criteria } = Shopware.Data;
import template from './store-settings-page.html.twig'
Component.register('store-settings-page', {
template,
inject: [
'repositoryFactory'
],
metaInfo() {
return {
title: this.$createTitle()
};
},
data: function () {
return {
entity: undefined,
storeData: null,
entityId: '4e2891496c4e4587a3a7efe587fc8c80',
secret_key: 'hdkkjjsmk538dncbjmns',
public_key: '1destinoDet2123lefmoddfk##$$%O',
}
},
computed: {
storeKeysRepository() {
return this.repositoryFactory.create('store_keys');
},
},
created() {
this.storeKeysRepository
.get(this.entityId, Shopware.Context.api)
.then(entity => {
this.entity = entity;
});
console.log(entity);
},
});
Apologies if my knowledge of Vue & JS is a bit off, based on how I see Shopware codes it, I recommend data to be written like this:
data() {
return {
...
};
}
I would also try to strip your file to the bear minimum to see when the error disappears.
Another thing to check is if you are running a JS file or TS file. Maybe it's having a hard time parsing your file because you are extending store-settings-page and it assumes it should be TypeScript?
this.storeKeysRepository
.get(this.entityId, Shopware.Context.api)
.then(entity => {
this.entity = entity;
console.log(this.entity);
});
This will do the trick

How to get the this instance in vue 3?

In vue 2+ I can easily get the instance of this as a result I can write something like this,
// main.js
app.use(ElMessage)
// home.vue
this.$message({
showClose: true,
message: 'Success Message',
type: 'success',
})
What should I do for vue 3 as,
Inside setup(), this won't be a reference to the current active
instance Since setup() is called before other component options are
resolved, this inside setup() will behave quite differently from this
in other options. This might cause confusions when using setup() along
other Options API. - vue 3 doc.
Using ElMessage directly
ElementPlus supports using ElMessage the same way as $message(), as seen in this example:
import { ElMessage } from 'element-plus'
export default {
setup() {
const open1 = () => {
ElMessage('this is a message.')
}
const open2 = () => {
ElMessage({
message: 'Congrats, this is a success message.',
type: 'success',
})
}
return {
open1,
open2,
}
}
}
Using $message()
Vue 3 provides getCurrentInstance() (an internal API) inside the setup() hook. That instance allows access to global properties (installed from plugins) via appContext.config.globalProperties:
import { getCurrentInstance } from "vue";
export default {
setup() {
const globals = getCurrentInstance().appContext.config.globalProperties;
return {
sayHi() {
globals.$message({ message: "hello world" });
},
};
},
};
demo
Note: Being an internal API, getCurrentInstance() could potentially be removed/renamed in a future release. Use with caution.
Providing a different method where the idea is to set a globally scoped variable to the _component property of the viewmodel/app or component:
pageVM = Vue.createApp({
data: function () {
return {
renderComponent: true,
envInfo: [],
dependencies: [],
userGroups: []
}
},
mounted: function () {
//Vue version 3 made it harder to access the viewmodel's properties.
pageVM_props = pageVM._component;
this.init();
},

How do I use API to fetch data for chart in the context of Vuejs

I'm new to Vuejs, and I want to make my code effective by fetching the data from API rather than giving the data directly.
Here is my code:
<template>
<canvas id="myChart" width="550" height="300"></canvas>
</template>
<script>
export default {
name: 'Chart',
data: () => ({
arrdate: [
1600934100.0,
1602009600.0,
1602747060.0,
1603050158.390939,
1603305573.992575
],
arrchallenge: [
9.0,
9.5,
2.5,
11.52,
12.4
]
}),
mounted () {
// eslint-disable-next-line no-unused-vars
const data = this.arrdate.map((arrdate, index) => ({
x: new Date(arrdate * 1000),
y: this.arrchallenge[index]
}))
const ctx = document.getElementById('myChart').getContext('2d')
// eslint-disable-next-line no-undef,no-unused-vars
const myChart = new Chart(ctx, {
type: 'line',
data: {
datasets: [
{
data,
label: 'Performance',
borderColor: '#7367F0'
}
]
},
options: {
scales: {
xAxes: [
{
type: 'time',
time: {
unit: 'month',
displayFormats: {
month: 'MMM YYYY'
}
}
}
],
yAxes: [
{
ticks: {
// eslint-disable-next-line no-unused-vars
callback (value, index, values) {
return `${value }%`
}
}
}
]
}
}
})
}
}
</script>
As you can see, the "date" and "challenge" contains data which is fed directly, but I want to fetch data from API.
What my API returns:
{
"date": [
1600934100.0,
1602009600.0,
1602747060.0,
1603050158.390939,
1603305573.992575
],
"challenge": [
9.1
9.5
-2.8
18.52
15.4
]
}
So as you can see my API, I want the "date's" data to be in arrdate and "challenge's" data to be in arrchallenge by using API.
Someone please help me with this, and if someone knows the answer please send me the changes by adding it to my code itself because I'm new to vuejs wrapping the contents would be difficult for me.
first add axios to your project and read the link below from vue documentation:
using axios with vue
after that you have two options:
Call API on page load
with this option your API calls as soon as your vue app loads so in your created hook do the API call like this:
created() {
axios.get('yourAPIUrl').then((response) => {
// reassign date and challenge with the response from the API call here for example:
this.date = response.data.date;
this.challenge = response.data.challenge
});
}
basically what it does is that you call the API when your vue is created and in the then part you use the response to updata the variables defined in your data object.
Call API on button click
with this method you have a button on your page like this:
<button #click="callAPI">get data from server</button>
when you click the button it calls the callAPI method and in your methods you have the same code as before, like this:
methods: {
callAPI() {
// same code as in the created example
}
}
you can also use async ... await syntax for API call if you want to.
also you can read this article on how to install and use axios in your project:
use axios API with vue CLI
I created this API for you to use to test out the solutions provided by anyone:
https://wirespec.dev/Wirespec/projects/apis/Stackoverflow/apis/fetchChartDataForVueJs
And here is the response:
https://api.wirespec.dev/wirespec/stackoverflow/fetchchartdataforvuejs
You can also create your own API on Wirespec and use it to generate more data (sequential or random) if you need more diverse testing.

Vuejs 'beforeunload' event not triggered as expected

I have registered 'beforeunload' event on created hook of the component used by routes of vue router.
I want to call this event handler in order to remove user on browser tab close or browser tab refresh or browser close.
On ComponentA
created (){
window.addEventListener('beforeunload', () => {
this.removeUser()
return null
})
}
Smilarly on ComponentB
created (){
window.addEventListener('beforeunload', () => {
this.removeUser()
return null
})
}
And my router.js
{
path: '/staff/call/:session_key',
name: 'Staff Call',
component: ComponentA,
meta: {auth: true}
},
{
path: '/consumer/call/:session_key',
name: 'Consumer Call',
component: ComponentB
},
Here 'beforeunload' event handler is triggered randomly. That is sometimes it get triggered and sometimes not. I count find any pattern when it is triggered and when it is not.
What am I missing here?
Edit
I'd guess the most likely culprit then is exactly what #PatrickSteele said. From MDN:
Note: To combat unwanted pop-ups, some browsers don't display prompts
created in beforeunload event handlers unless the page has been
interacted with; some don't display them at all. For a list of
specific browsers, see the Browser_compatibility section.
I'd say it's likely you're seeing inconsistent behavior because you are sometimes not interacting with the page.
This may be a syntax error. created should be a method
created () {
window.addEventListener('beforeunload', this.removeUser)
},
methods: {
removeUser () {
//remove user here
}
}
A fiddle working: https://jsfiddle.net/e6m6t4kd/3/
It's work for me. while do something before reload or close in
vue.js
created() {
window.onbeforeunload = function(){
return "handle your events or msgs here";
}
}
I had to do some fiddling on the above examples, I believe this is the most robust solution:
let app1 = new Vue({
delimiters: ['[[', ']]'],
el: '#app',
data: {
dirty_form: true,
},
created () {
console.log('created')
window.addEventListener('beforeunload', this.confirm_leaving)
},
methods: {
confirm_leaving (evt) {
if (this.dirty_form) {
const unsaved_changes_warning = "You have unsaved changes. Are you sure you wish to leave?";
evt.returnValue = unsaved_changes_warning;
return unsaved_changes_warning;
};
};
},
});
If you want detect page refresh/change in Vue whenever you press F5 or Ctrl + R, You may need to use Navigation Timing API.
The PerformanceNavigation.type, will tell you how the page was accessed.
created() {
// does the browser support the Navigation Timing API?
if (window.performance) {
console.info("window.performance is supported");
}
// do something based on the navigation type...
if(performance.navigation.type === 1) {
console.info("TYPE_RELOAD");
this.removeUser();
}
}
Not sure why none of the above were fully working for me in vue 3 composition api. Abdullah's answer partially works but he left out how to remove the listener.
setup() {
const doSomething = (e) => {
// do stuff here
return true
}
onBeforeMount(() => {
window.onbeforeunload = handleLeaveWithoutSaving
})
onUnmounted(() => {
window.onbeforeunload = null
})
}

Cant mount children component to ref

I have a problem with VuePaginator , that I can mount it to my Vue app $refs properties. I am doing everyting according to docs, here is my component in the html:
<v-paginator :resource.sync="comments" ref="vpaginator" resource_url="{{route('api.item.comments', $item->pk_i_id)}}"></v-paginator>
The pagination works correctly, but I can't trigger fetchData() from the vuejs code, because paginator is not getting mounted to vm.$refs.vpaginator.
Here is the code that I use:
var app = new Vue({
el: '#comments',
data : {
comments: [],
newComment: {
text: ""
}
},
components: {
VPaginator: VuePaginator
},
methods: {
addComment: function(comment){
var vm = this;
this.$http.post($('meta[name="item-url"]').attr('content'), comment)
.then(function(response){
toastr.success(response.data.result);
comment.text = "";
vm.$.vpaginator.fetchData();
}).catch(function (error) {
if(error.data){
toastr.error(error.data.text[0]);
}
})
},
logRefs: function(){
console.log(this.$refs.vpaginator);
}
}
});
I have created logRefs() function to check the $ref property and it is always undefined.
Since you are using the Version 1 of VueJS, usage is a bit different - check this demo http://jsbin.com/rupogesumo/edit?html,js,output
<v-paginator :resource.sync="comments" v-ref:vpaginator resource_url="{{route('api.item.comments', $item->pk_i_id)}}"></v-paginator>
Docs Reference: https://v1.vuejs.org/api/#v-ref