How to access the window object in vue js? - vue.js

I have this vue js component:
<template>
<div>
hello world
</div>
</template>
<script>
export default {
name: 'mycomp',
data: function () {
console.error("window.google_recaptcha_public_key", window.google_recaptcha_public_key);
return {
}
},
mounted() {
let app = this;
console.error("window.google_recaptcha_public_key2", window.google_recaptcha_public_key);
},
}
</script>
<style scoped lang="scss">
</style>
returns:
window.google_recaptcha_public_key undefined
window.google_recaptcha_public_key2 undefined
where can I leave painless and happy all global configuration?
notice this configuration lives in my laravel backend. So I wont copy paste all values from the backend to the front end

U can use Vue.prototype in main.js file, or in file you import Vue
Vue.prototype.Hereanyname = window.hereanyname;
and in your Vue application, you can use it
Hereanyname.thefunction
Real example on Laravel
in main.js
import Vue from 'vue';
Vue.prototype.Routes = window.routes;
new Vue({
el: '#app',
template: '<App/>',
components: {App}
});
in your application
:href="Routes.route('laravel.route.here')"
So for your case
import Vue from 'vue';
Vue.prototype.GoogleRecaptcha = window.google_recaptcha_public_key;
new Vue({
el: '#app',
template: '<App/>',
components: {App}
});
inside application
mounted() {
console.log(this.GoogleRecaptcha)
}

In Vue3, you no longer have the global Vue instance, so you need to assign the window as a global property on your app...
// main.js
app.config.globalProperties.window = window
Then in your components, window will just work.
This info is from an impeccable source.

You should save your window variable in Vue.prototype
main.js
Vue.prototype.$authUser = window.authUser;
After that, you can access your data as follows:
Vue template
<div v-text="$authUser.name"></div>
Vue script
let name = this.$authUser.name;

window is available in the vuex store. This may help if you need to mutate the window property synchronously with other actions/mutations, give you a chance to validate what goes into it, or catch an error if the variable you intend to put there isn't available.
export default new Vuex.store({
state: {
windowFoo: window.foo,
googleRecaptcha: window.google_recaptcha_public_key
},
getters: {
windowFoo: (state) => state.windowFoo,
googleRecaptcha: (state) => state.googleRecaptcha
},
actions: {
barThenFooThenBaz({ commit }, { foo }) {
// ... do some other required actions first
commit("setWindowFoo", foo);
// ... do some dependent actions next
}
},
mutations: {
setWindowFoo(state, foo) {
state.windowFoo = foo;
}
}
});
Then from your Single File Component...
//....
computed: {
windowFoo() {
return this.$store.getters.windowFoo;
},
googleRecaptcha() {
return this.$store.getters.googleRecaptcha;
}
},
methods: {
async barThenFooThenBaz(foo) {
await this.$store.dispatch({
type: "barThenFooThenBaz",
foo: foo
});
// ... do something dependent on windowFoo being set
}
}
//....
Although the other answers here are totally acceptable, I've had issues using the Vue instance with Vue.prototype in main.js as our project has gotten larger, so I hope this helps!

Provide/Inject works nicely. Here's an example with Vue 3:
main.js
const app = createApp(App)
app.provide('recaptcha_key', window.google_recaptcha_public_key)
app.mount('#app')
MyComponent.vue
<script setup>
const { inject } from 'vue'
const recaptchaKey = inject('recaptcha_key')
</script>

Related

access component from .js file vuejs

I am using: https://www.npmjs.com/package/vue-loading-overlay
My main.js file looks like:
import Vue from 'vue'
import App from './App.vue'
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
And App.vue:
<template>
<div id="app">
<loading
:active.sync= "isLoading"
:can-cancel= "false"
:is-full-page= "false">
</loading>
<router-view></router-view>
</div>
</template>
<script>
//import Vue from 'vue';
import Loading from 'vue-loading-overlay';
import 'vue-loading-overlay/dist/vue-loading.css';
//Vue.use(Loading);
export default {
data() {
return {
isLoading: true
}
},
name: 'App',
components: {
Loading
}
}
</script>
<style>
</style>
This seems to work fine, but how can I manipulate the isLoading to be true or false, from main.js? I might be building a function or something in main.js for future use, and instead of having the <loading> on each view page, I would prefer to be able to control it globally some how.
I haven't tested this, but based on the referenced answer in my comment, this might work:
main.js
new Vue({
el: '#app',
props: ['isLoading'],
components:{App},
template: '<App v-bind:isLoading="true">'
})
You would have to make isLoading a prop in App.vue. The v-bind part above should make the prop reactive.
Also, you could create a bus and send events from main.js to App.vue, then update isLoading accordingly.
You should use store for it.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
let store = new Vuex.Store({
state: {
isLoader: false,
},
getters: {
isLoader(state) {
return state.isLoader
},
},
mutations: {
isLoader(state, status) {
state.isLoader = status
},
},
actions: {
isLoader({commit}, status) {
commit('isLoader', status)
},
}
})
everywhere in your application you can set the isLoader to true using dispatch
vue.$store.dispatch("isLoader", true/false);

How to make reactive array in nativescript vue?

I know that vue doent detect change in array when we directly set an item with the index, instead, Vue.set is used, and works fine in vue.js. But i am using Vue with native script, and when I use Vue.set(myArray,index,newValue), give error. ReferenceError Vue is not defined.
Here is my script:
<script>
export default {
methods: {
comparar: function(caracter, pos) {
//This is NOT reactive
this.palabra_escrita[pos] = caracter
// This must be reactive but throws me error
app.$set(this.palabra_escrita, pos, caracter)
}
}, //End methods
data() {
return {
palabra_escrita: [],
};
}
};
</script>
Here is my app.js file:
import Vue from 'nativescript-vue';
import HelloWorld from './components/HelloWorld';
// Uncommment the following to see NativeScript-Vue output logs
//Vue.config.silent = false;
new Vue({
template: `
<Frame>
<HelloWorld />
</Frame>`,
components: {
HelloWorld
}
}).$start();

How do I create a Vue bus for global event handling?

I'm using Vue on a Node/Webpack/Vue Router environment and trying to setup a global event handler or bus. But it's not working. It's showing up as undefined. Here's my setup:
main.js:
//Declare event handler
Object.defineProperty(Vue.prototype, '$bus', {
get () {
return this.$root.bus
}
})
//Declare app instance
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
App.vue
<script>
export default {
name: 'App'
created: () => {
console.log(this.$bus);
}
}
</script>
The console.log statement returns undefined, meaning the event handler somehow isn't getting passed to the app. I've also tried the following statement to declare the event handler:
main.js
//Declare event handler
const eventBus = new Vue()
Vue.prototype.$bus = eventBus
But that doesn't work either.
This is a problem with using the arrow function. While the () => {} syntax looks nicer than function() {}, there is a difference, in that the the arrow function uses a lexical context for this (from where it was defined, instead of from where it was called, which id what you need in this instance), meaning that this is no longer the Vue instance, so you cannot use this.$bus. You can fix this by replacing the arrow function with a regular function using either created: function() {... or the concise (but functionally equivalent) version created() {...
You can read up more on the differences by looking up articles on es6, arrow functions, lexical scope, this context.
main.js code:
import Vue from "vue";
import App from "./App";
Vue.prototype.$bus = new Vue();
new Vue({
el: "#app",
components: { App },
template: "<App/>"
});
somewhere in app.js
export default {
name: "App",
created() {
console.log(this.$bus);
}
};

Call a VueJS method inside a component outside 'export default'

I'm trying to call a function inside 'method' from outside. However, it isn't working.
Github issue reporting the same: https://github.com/vuejs/vue/issues/329
vm.test(); // call a function in method, not working
this.vue.test() // not working
export default {
methods: {
test: function() {
alert('test fuction called');
}
}
}
It is not very clear what the actual goal of the original poster is, however this is how you can call a method on a Vue instance, after creating it:
var viewModel = new Vue({
el: "#app",
data: {
msg: "Hello there"
},
methods: {
test: function() {
alert('test fuction called');
}
}
});
viewModel.test();
Working example: https://jsfiddle.net/Daryn/Lja7pake/3/
If you are exporting a single file component then try this:
example.js
<script>
export default {
methods: {
test: function() {
alert('test fuction called');
}
}
}
</script>
main.js
<script>
import Thing from './example.js';
Thing.test();
</script>
Reference: https://v2.vuejs.org/v2/guide/single-file-components.html
What you are trying to achieve is fundamentally flawed. You can't call a method of a component unless you have a reference to an instance of that particular component. In your code, which particular component is vm referring to?
All you're doing is exporting a Vue component definition from your module; there's no component being instantiated here.
We'll need to see more of your code or a complete explanation of what exactly you're trying to achieve so we can provide an alternative solution. (Why are you trying to call the component's method outside of its definition?)
export default {
...
methods: {
...
},
mounted () {
EventBus.$on(‘EVENT_NAME’, function (payLoad) {
...
});
}
}
This is the way I solved that problem.
For the purpose of this demonstration, we create a new project using Vue/CLI. After installation finished, we make the vm exposed to global. Open src/main.js and edit like so:
src/main.js
import Vue from 'vue';
import App from './App.vue';
var vm = new Vue({
router,
render: h => h(App)
}).$mount('#app');
// Add this line (tambahkan baris berikut):
window.vm = vm;
Leave the generated App.vue like it is. So the first child of vm (vm.$children[0]) is App.vue.
We see that App.vue have a child. That makes HelloWorld.vue component as a grand children of vm (vm.$children[0].$children[0]). Knowing this, we can call the methods from outside 'export default' like this:
src/components/HelloWorld.vue
<template>
<div class="hello">
<button
id="sebuahButton"
class="btn btn-outline-secondary btn-sm"
type="button"
>Click Me, Jose!</button>
<h1>{{ msg }}</h1>
<!-- and some stuff, vue cli default generated code -->
<div>
</template>
<script>
(function() {
// wait for the DOM ready event in plain JavaScript
document.addEventListener("DOMContentLoaded", event => {
document.getElementById("sebuahButton").onclick = function() {
vm.$children[0].$children[0].someAction();
};
});
})();
export default {
name: "HelloWorld",
props: {
msg: String
}
methods: {
someAction () {
// do something (lakukan sesuatu masbro!)
console.log("It's been called from outer space, Luke!");
}
}
}
</script>

User editable Vue template

In my app, I have a template for things like Invoice, Email etc. I'd like the user to be able to edit these templates by dragging and dropping elements. I'm currently using vue-loader along with webpack to pre-compile my vue files into pure JS.
Is it possible to load a vue template from the database on the fly? I've seen this post but this isn't using vue-loader so I'm not sure how to override the template on my component via the code. Something like:
created: function () {
this.$template = '<html><p>Loaded from the DB!</p></html>'
}
would be useful. Is this possible?
Edit: I've tried the following but I get an error Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.:
created: function () {
document.body.innerHTML = '<html><p>I AM FROM THE DB {{total}}</p></html>'
}
This would need to be modified to pass in the templates from your database, but this works in a very simple single file component. Obviously you will want to customize, but this demonstrates the concept.
Dynamic.vue
<script>
export default {
props:["template"],
data(){
return {
message:"hello"
}
},
created(){
this.$options.template = this.template
}
}
</script>
App.vue
<template>
<div>
<dynamic
v-for="template, index of templates"
:template="template" :key="index">
</dynamic>
</div>
</template>
<script>
import Vue from "vue"
import Dynamic from "./Dynamic.vue"
export default {
name: 'app',
data () {
return {
templates: [
"<h1>{{message}}</h1>",
"<h4>{{message}}</h4>"
]
}
},
components:{
Dynamic
}
}
</script>
main.js
import Vue from 'vue'
import App from './App.vue'
new Vue({
el: '#app',
render: h => h(App)
})