Access global computed properties in <script> tag - vue.js

Vuepress defines some global properties than can be used in templates, like $page or $site.
https://github.com/vuejs/vuepress/blob/master/packages/docs/docs/guide/global-computed.md
I can use these within the <template> node, but trying to use them within <script> throws an error.
<template>
<div class="page">
<div class="content">
<div>{{ $page.frontmatter.description }} Works fine</div>
<div>{{ $frontmatter.description }} Does not work despite what's in docs</div>
<div>{{ description }} Doesn't work</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
description: this.$page.frontmatter.description, //not defined
description2: $page.frontmatter.description, //nor this
};
},
};
</script>

Your problem is not about using Vuepress Global Computed Properties inside <script> tag, it's actually about using Vuejs Computed Properties inside data().
If you simply create a Vue component like the code snippet below, you will find the variable testMessage is not defined either.
<template>
<div>{{ testMessage }}</div>
</template>
<script>
export default {
data() {
return {
testMessage: this.test
}
},
computed: {
test: function() {
return 'This is a test';
}
}
}
</script>
I don't know the exact reason for this, but I believe it's about the lifecycle of Vue instance. So I suggest you simply access the Global Computed Properties inside computed properties or methods:
<template>
<div>{{ description }}</div>
</template>
<script>
export default {
computed: {
description : function() {
return this.$page.frontmatter.description;
}
}
}
</script>

Related

Why won't vue.js update the DOM?

Working my way learning about Vue. I chose it as the better alternative after looking at React, Angular and Svelte.
I have a simple example that its not working probably because I'm not getting/understanding the reactive behaviour of Vue.
Plain simple App:
<template>
<div id="app">
<app-header></app-header>
<router-view />
<app-footer></app-footer>
</div>
</template>
<script>
import Header from './components/Header.vue'
import Home from './components/Home.vue'
import Footer from './components/Footer.vue'
export default {
components: {
name: 'App',
'app-header': Header,
'app-footer': Footer
}
}
</script>
Where Home.vue and Footer.vue have plain HTML content on the template.
On Header.vue I have:
<template>
<div>
<h1>The Header</h1>
<nav>
<ul>
<li>Curr Player: {{ ethaccount }}</li>
<li>Prop owner: {{ propOwner }}</li>
</ul>
</nav>
<hr />
</div>
</template>
<script>
export default {
data() {
return {
ethaccount: 'N/A',
propOwner: 'N/A'
}
},
methods: {
update() {
var ethaccount = '0xAAAAAA123456789123456789123456789'
console.log('ETH Account: ' + ethaccount)
var propOwner = '0xPPPPPPPPPPP987654321987654321'
console.log('Prop Account: ' + propOwner)
}
},
mounted() {
this.update()
}
}
</script>
But I'm unable to get the header updated and unable to find what I'm doing wrong. Help.
If you need to read a little bit more about the reactivity of the datas in vuejs check this link : https://v2.vuejs.org/v2/guide/reactivity.html
If you need to access/change your data try to do it like that :
this.$data.ethaccount = 'foo';
this.$data.propOwner = 'bar';
For me the problem is taht you re-declare your variable locally by doing :
var ethaccount = "0xAA...";
By doing such you never change the value of the data you're accessing through your template.
Hope it will solve your problem.

vuejs passing method to child dynamically

I have a 3rd party component <third-party-component /> which accepts following event:
onAdd, onRemove, onUpdate
I want to create a wrapper component around it and want to pass these events dynamically so that can handle the response in wrapper component, something like
wrapper.js
<template>
<div class="my-wrapper">
<third-party-component />
</div>
<template>
using-wrapper.js
<template>
<div>
...
<wrapper #onAdd="add" #onRemove="remove"></wrapper>
...
</div>
</template>
<script>
export default {
methods: {
onAdd() {
console.log('on add in using-wrapper.js');
},
onRemove() {
console.log('on remove in using-wrapper.js');
}
}
}
</script>
You can pass all attributes and listeners by binding them using v-bind and v-on
You also need to set inheritAttrs to false
https://v2.vuejs.org/v2/api/#inheritAttrs
<template>
<div class="my-wrapper">
<third-party-component v-bind="$attrs" v-on="$listeners"/>
</div>
<template>
using-wrapper.js
<template>
<div>
...
<wrapper #onAdd="add" #onRemove="remove"></wrapper>
...
</div>
</template>
<script>
export default {
inheritAttrs: false,
methods: {
onAdd() {
console.log('on add in using-wrapper.js');
},
onRemove() {
console.log('on remove in using-wrapper.js');
}
}
}
</script>
Well on "wrapper" you will need to create 3 methods that listen and get triggered on "third-party-component".
<template>
<div class="my-wrapper">
<third-party-component #onAdd="wrapperAdd" #onRemove="wrapperRemove" #onUpdate="wrapperUpdate" />
</div>
<script>
export default {
methods:{
wrapperAdd(){
this.$emit("onAdd",{obj that will get to the parent});
}
}
}
I made only 1 method because the other 2 are similar.

How to bind a prop value using a function and pass it to another component

Is it possible to bind a prop to a function?
In my example below I’m trying to get a value from a function in the main App.vue and pass it as a prop to the child component customComponent.
e.g. (this example doesn’t work)
App.vue
import customComponent from ‘./custom-component.vue'
<template>
<custom-component
v-bind:myValue="geMyValue()"
></custom-component>
</template>
<script>
export default {
name: "Item",
methods: {
getMyValue: function() {
return 1+3;
}
}
}
</script>
customComponent.vue
<template>
<h3 class="some-custom-layout">custom component</h3>
<input type="button" #click="sendMyValue()" />
</template>
<script>
export default {
name: “custom",
props: ['myValue']
methods: {
sendMyValue: function() {
console.log(this.myValue);
}
}
}
</script>
It's possible, but probably it would be better to use computed properties, if you are going to return value:
<template>
<custom-component
v-bind:myValue="myValue"
></custom-component>
</template>
<script>
export default {
name: "Item",
computed: {
myValue: function() {
return 1+3;
}
}
}
</script>
https://v2.vuejs.org/v2/guide/computed.html

asyncData in component of Nuxtjs isn't working

I have an issue with the nuxt.js project. I used async the component but when it rending, async wasn't working. This is my code.
I have view document in https://nuxtjs.org/api/ but I don't know what is exactly my issue
Test.vue (component)
<template>
<div>
{{ project }}
</div>
</template>
<script>
export default {
data() {
return {
project : 'aaaa'
}
},
asyncData() {
return {
project : 'bbbb'
}
}
}
</script>
This is index.vue (page)
<template>
<test></test>
</template>
<script>
import Test from '~/components/Test.vue'
export default {
components : {
Test
}
}
</script>
My expected result is
bbbb
But when running on http://localhost:3000 this is actual result
aaaa
I try to search google many times but don't have expected solution for me. Someone help me, please.
Thanks for helping.
The components/ folder must contains only "pure" Vue.js components
So you can't use asyncData inside.
Read this FAQ: https://nuxtjs.org/faq/async-data-components#async-data-in-components-
components/Test.vue (component)
<template>
<div>
{{ project }}
</div>
</template>
<script>
export default {
props: ['project'] // to receive data from page/index.vue
}
</script>
pages/index.vue (page)
<template>
<test :project="project"></test>
</template>
<script>
import Test from '~/components/Test.vue'
export default {
components : {
Test
},
asyncData() {
return {
project : 'bbbb'
}
}
}
</script>
You cannot use asyncData in component.
You can choose to use the fetch method instead.
<template>
<div>
<p v-if="$fetchState.pending">Loading....</p>
<p v-else-if="$fetchState.error">Error while fetching mountains</p>
<ul v-else>
<li v-for="(mountain, index) in mountains" :key="index">
{{ mountain.title }}
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
mountains: []
}
},
async fetch() {
this.mountains = await fetch(
'https://api.nuxtjs.dev/mountains'
).then(res => res.json())
}
}
</script>

Property or method is not defined on the instance in v-bind:class but is in data

I have my component:
<template>
<div class="snack-visible" :class="{'snack-danger':!success, 'snack-success':success }">
<div>
<strong>{{message}}</strong>
</div>
</div>
</template>
<script>
export default {
data(){
return{
showing: false,
message:"",
success:false
}
}
//here other methods and created();
}
So i have defined variables in data, but it return these errors:
app.js:11624 [Vue warn]: Property or method "success" is not defined
on the instance but referenced during render. Make sure to declare
reactive data properties in the data option.
found in
---> at /var/www/html/carrozzeria/resources/assets/js/components/Snackbar.vue
you can check it out by like this :
<template>
<div class="snack-visible" :class="success ? 'snack-success' : 'snack-danger'">
<div>
<strong>{{message}}</strong>
</div>
</div>
</template>
<script>
export default {
data(){
return{
showing: false,
message:"",
success:false
}
}
//here other methods and created();
}
</script>
Ther problem was that I didn't put tag < /script> on end file