Set "this" keyword of App.vue in Vuex state - javascript

I found a seloution for how to access to vue-router and other services that works only inside the vue component. In the created option of App.vue i save the "this" of vue app inside state of vuex.
does it's a good way or can make some problems in future?
instead to write:
this.$router.push('route-name')
from some component, is save the this keyword in the state as context key for example,
and now from the Actions i'm using the context instead this
such like this:
state.context.router.push('route-name')
and its works..
my question is if its good solution or not.

I think that is not a good solution, if you want to use this, you should try with the actions or getter returned value, inside a Vue file instead using it directly in an action.
I'm giving an example and an explanation
Example:
Getter:
export function getRedirect(state){
return state.routerName
}
Vue file:
<template>
Page
<button #onClick="redirect" > Redirect </button>
</template>
<script>
import {mapGetters} from 'vuex'
export default: {
computed:{
...mapGetters('VuexStoreName',['getRedirect'])
},
methods:{
redirect(){
this.$router.push(this.getRedirect)
}
}
}
</script>
So, instead of using the redirect inside an JS file, creating an action and passing this inside the parameter or getting it by state, you'll be using it correctly in a Vue file.
The probblem setting this in the state is that when it changes the instance saved will not change, and you'll have to update every time and everywhere. And calling this inside a Vue file, it'll always be updated

Related

Why Vue .sync command not working in router view?

I'm trying to sync a variable between components using the .sync command in Vue. It works without problems when I put components in the page using the tag (for example: <my-component></my-component>). When I bind it in a <router-view>, it works only one-way. Is it normal?
When I click on the link inside the component, it does not change the value of test in the root Vue object. When I change it in the root object, the component inherits the value correctly.
Click here for an example
You are trying to update the prop directly, the correcto way to update it is to emit an update. Remember :test.sync is a shorthand to v-bind:test and v-on:update:test
On your Foo component:
editTest: function() {
this.$emit('update:test', false) // instead of this.test = false;
}
Fiddle: https://jsfiddle.net/hansfelix50/u7k5qpwz/

Vue.js Passing variable from one component to another (jQuery)

I have a component called ShowComment and a component called EditComment.
In ShowComment there is a variable this.CommentRecID. I want to use this variable in the component EditComment.
The problem is that a console.log(this.CommentRecID); shows that the variable is undefined in EditComment, but defined in ShowComment, but I don't know why it's undefined:
I used this to "use" this.CommentRecID in EditComment, but I don't know if this is the correct way to do it because it's related to jquery:
import * as $ from "jquery";
import DatePicker from "vue2-datepicker";
export default {
props: ["CommentRecID"],
components: { DatePicker },
Here's the full ShowComment component: https://pastebin.com/fcy4PCq0
Here's the full Editcomment component: https://pastebin.com/uik7EwD1
I'm fairly new to Vue.js. Does someone know how one can solve this issue?
You should not use jQuery and Vue.js at the same time.
You should try to use props to send data from parent to child.
You could add EditComment as an element in your ShowComment something like this:
<EditComment CommentRecID="this.CommentRecID" v-if="showEdit" />
And toggle the showEdit flag from the editItem method
editItem() {
this.showEdit = true
}
If you want to show a modal, then your EditComment component is probably up the tree so you could either use EventBus or use Vuex.
It seems like you are already using Vuex in your project, so add a mutation that stores the CommentRecID and use it in a similar manner to show the dialog.
You can use Vue Props to easily solve this problem, you have to send the variable from parent component to child component, please check this PROPS documentation out, its self explanatory:
Props Vuejs documentation
please let me know if you find trouble in using props

loading data into vuex store before app loads, how to accomplish this?

I am making a dispatch call to my store inside the created hook of App.vue, in a child component I then ask for that with a getter, the issue seems to be that when loading the app the child component is loaded before the data has been placed in the store and does not display. I am confident about this from the fact that I console logged and the first log is the child component who is the consumer of the store. How can I guarantee that the dispatch which is needed site wide happens before any other components are loaded?
// App.vue
created() {
this.$store.dispatch(this.$mts.diseases.DISEASES_LIST) //note I tried with async/await to no avail
...
//child component
created() {
this.diseases = this.$store.getters.diseasesList
...
As noted I tried to make the code inside the App.vue asyn but it seems that's it's not loading first so this did not help.
You should put the property inside a computed in your child component, that way it will populate as soon as the value exists in your store
computed: {
diseases () {
return this.$store.getters.diseasesList
}
}
See the VueX docs
If you want to wait for the data to be available before loading the component then you can use v-if see docs
<your-component v-if="$store.getters.diseasesList">
...
</your-component>
Consider using Nuxt.js (https://nuxtjs.org/) it has fetch and asyncData support out of the box, so that component won't render before the promises they return are solved.

Variable not defined when used outside of Vue <template>

I am exporting a value from a JS file and using it in my Vue. I display the value like in my template, but I would like to also use this value elsewhere, outside of the template.
Here is a simplified version of my setup and what I would like to achieve:
In my myJS.js (in actual app this file is used to call my API):
const appService = {
getPosts() {
return 123456;
}
}
export default appService
and then I have a VUE component that looks like this:
<template>
{{ info }}
</template>
alert(info);
import appService from '../myJS'
export default {
name: 'myvue',
props: {
msg: String
},
data () {
return {
info: {}
}
}
async created () {
this.info = await appService.getPosts();
}
}
The value is displayed in the template, but the alert(info) triggers a 'info is undefined' error.
How can I use this value in normal JavaScript outside of my template?
Hope that makes sense.
Thanks in advance!
There's basically two ways:
Assign the value to a variable, inside the file, but outside the component definition. So in your example you would say let info; and in your created() hook you would go this.info = info = await appService.getPosts().
Assign the component itself to a variable before you export it:
const myComponent = { component definition... }
// Access with myComponent.info
export default myComponent;
However! You will see that myComponent.info is initially undefined. And unlike in the template, the value of info will not reactively update when the asynchronous call resolves. Reactivity magic only works in the template and in the code of the actual component, e.g. in computed and watch properties. How to handle the specifics of asynchronous loading elegantly really depends on the specifics of how you want to use this variable.
Finally: the reason you don't just get access to the variable throughout the .vue file is because under the hood, the template compiles to a function which is executed in the context of the component. For convenience, all of the fields of the component are then made available as variables without the usual this prefix. In fact, in your template, info is treated as a shorthand for this.info. (Notice that you can substitute this.info for info in the template and it will still work.) This privilege doesn't apply to any other code in the file; that stuff is just vanilla js code.

why can't use window in vue template?

i set a property in window Object for using it globally, like this:
window.configs.foo=true;
but when use it like this:
<v-btn v-if="window.configs.foo">go</v-btn>
in console, i get this error:
[Vue warn]: Property or method "window" is not defined on the instance
but referenced during render. Make sure that this property is
reactive, either in the data option, or for class-based components, by
initializing the property.
how i can use window object in vueJs template?
Because v-if is intended to be used on properties of your component. You cannot v-if over variables in global scope, or outside your component data or properties.
What you can do, instead, if to setup a computed property on your component that targets window.configs.foo:
new Vue({ // or maybe a component, this depend on how you're using it
template: `<div>
<v-btn v-if="showMyButton">...</v-btn>
</div>`
computed: {
showMyButton() {
return window.configs && window.configs.foo;
}
}
})
UPDATE:
If you have to reuse this in a lot of sites, there are two things that you can do:
Vuex
Using vuex to set the showMyButton as a vuex state. Then you can access it via:
v-if="$store.state.showMyButton"
And you can modify it via standard vuex mutations.
 Mixins
Maybe for some reason you don't want to use vuex. Then a way to reuse logic across many components is to use mixins.
const configAwareMixin = {
computed: {
showButton() {
return window.configs.foo;
}
}
}
// And then in your component:
Vue.component('stuff', {
mixins: [buttonAwareMixin],
template: `<div><v-btn v-if="showButton"></v-btn></div>`
})
Well, Alternate is to use $root in Vue. Define foo at your vue instance and it will be available in all the component with this.$root.foo.
Here is the official docs
Hope this helps
The only easiest solution is Vue.prototype.$window = window; in main.js from folder src and use can use window as $window inside your template. Hope can help you all.
I solved it by replacing the 'vue.js' with 'vue.min.js'! I don't know why.

Categories