How to use #nuxt/content inside Component? - vue.js

I'm trying to nuxt-contnt inside a component it works well in page with asyncData but not working inside the component
this works fine :
export default {
async asyncData({ $content }) {
const page = await $content('hello').fetch()
return {
page,
}
},
}
but this is not working :
export default {
data() {
return {
content: [],
}
},
async fetch({ $content }) {
this.content = await $content('hello').fetch()
},
}

fetch doesn't have any parameters but has access to this, so it should be
async fetch() {
this.content = await this.$content('hello').fetch()
}
https://nuxtjs.org/docs/features/data-fetching/

Related

Nuxt async fetch() doesn't update component property

I have a component that works perfectly with asyncData(), but i want to use fetch() instead. The problem is that when using fetch method, 'car' property is never updated. Am i missing something?
Doesn't work:
data() {
return {
car: null,
}
},
async fetch({ $axios, route }) {
this.car = await $axios.$get('/cars/' + route.params.id)
},
Works perfectly:
data() {
return {
car: null,
}
},
async asyncData({ $axios, route }) {
const response = await $axios.$get('/cars/' + route.params.id)
return { car: response.data }
},
If you use the fetch hook with something like fetch({ ... }), you'll be using the old fetch() hook.
If you want it to work, try out rather
async fetch() {
this.car = await this.$axios.$get(`/cars/${this.$route.params.id}`)
},
As confirmed in this github issue.

How to integrate paypal Payment Button Vuejs3 Composition API (setup function)

I'm trying to integrate PayPal buttons with my Vuejs3 project using Composition API (setup ) but all what i get is errors i try to integrate it without using setup and its working fine i leave the working script down
the esseu is i couldent pass data from data to methodes
<script>
import { inject, onMounted, ref } from "vue";
export default {
data() {
return {
loaded: false,
paidFor: false,
product: {
price: 15.22,
description: "leg lamp from that one movie",
img: "./assets/lamp.jpg",
},
};
},
setup() {
const store = inject("store");
console.log(store.state.prodects_in_cart);
return { store };
},methods:{
setLoaded: function() {
this.loaded = true;
paypal_sdk
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: this.product.description,
amount: {
currency_code: "USD",
value: this.product.price
}
}
]
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.data;
this.paidFor = true;
console.log(order);
},
onError: err => {
console.log(err);
}
})
.render(this.$refs.paypal);
}
},
mounted: function() {
const script = document.createElement("script");
script.setAttribute('data-namespace',"paypal_sdk");
script.src ="https://www.paypal.com/sdk/js?client-id=Here i pute my Client Id";
script.addEventListener("load", this.setLoaded);
document.body.appendChild(script);
},
};
</script>
the error i get when i use setup() is
The error image
my script using setup()
setup() {
const store = inject("store");
const paypal = ref(null);
let loaded = ref(false);
let paidFor = ref(false);
const product = {
price: 15.22,
description: "leg lamp from that one movie",
img: "./assets/lamp.jpg",
};
onMounted: {
const script = document.createElement("script");
script.setAttribute("data-namespace", "paypal_sdk");
script.src =
"https://www.paypal.com/sdk/js?client-id=AXDJPmFjXpXm9HMXK4uZcW3l9XrCL36AxEeWBa4rhV2-xFcVYJrGKvNowY-xf2PitTSkStVNjabZaihe";
script.addEventListener("load", ()=>{
loaded = true;
console.log('hello adil');
paypal_sdk
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: 'this is product description',
amount: {
currency_code: "USD",
value: 120.00,
},
},
],
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.data;
this.paidFor = true;
console.log(order);
},
onError: (err) => {
console.log(err);
},
})
.render(paypal);
});
document.body.appendChild(script);
}
return { store ,paypal};
}
paypal is a ref. You're currently passing to paypal_sdk the ref itself and not the inner value, which would be the template ref's element. To fix this, pass the ref's .value.
Your onMounted code is not properly invoked, as it must be passed a callback.
import { onMounted, ref } from 'vue'
export default {
setup() {
const paypal = ref(null)
onMounted(/* 2 */ () => {
const script = document.createElement('script')
//...
script.addEventListener('load', () => {
paypal_sdk
.Buttons(/*...*/)
.render(paypal.value) /* 1 */
})
})
return {
paypal
}
}
}
The reason why you are getting that error is because you are using option Api onMounted life cycle hook, instead of doing that use the vue 3 life cycle hooks for onMounted.
First you will have to import it from vue like this.
<script>
import {onMounted} from 'vue'
then you are going to use it like this.
return it as a call back function
onMounted(() => {
//all your code should placed inside here and it will work
})
</script>
Here is my answer using the paypal-js npm package
<template>
<div ref="paypalBtn"></div>
</template>
<script>
import { onMounted, ref } from 'vue';
import { loadScript } from '#paypal/paypal-js';
const paypalBtn = ref(null);
onMounted(async () => {
let paypal;
try {
paypal = await loadScript({
'client-id': 'you_client_id_goes_here',
});
} catch (error) {
console.error('failed to load the PayPal JS SDK script', error);
}
if (paypal) {
try {
await paypal.Buttons().render(paypalBtn.value);
} catch (error) {
console.error('failed to render the PayPal Buttons', error);
}
}
});
</script>

Nuxt Content async fetch in component

I'm new to the #nuxt/content module and it's working well except within components.
Here I'm trying to get the content like so:
layout.vue
export default {
name: 'Default',
CONTENT: 'content',
async asyncData({ $content }) {
const content = await $content('content').fetch()
return { content }
},
}
component.vue
export default {
async fetch({ $content }) {
this.content = await this.$content('content', { deep: true }).fetch()
},
data() {
return { content }
},
}
How can I use content within components?
So, there is no reason that $content will not work in components, I double-checked. It's just the way fetch works in comparison to asyncData.
You can read more about the differences here: https://nuxtjs.org/blog/understanding-how-fetch-works-in-nuxt-2-12/#asyncdata-vs-fetch
But it comes down to a different syntax when using the fetch hook, as follows:
export default {
data() {
return {
content: [],
}
},
async fetch({ $content }) {
this.content = await $content('content', { deep: true }).fetch()
// ! it's $content and not this.$content here since you've imported it in the scope
},
}

How to do mapGetters in asyncData? Nuxt

My goal is to pass a getter object inside asyncData, because I need to access the state to pass data to axios
Code example
export default {
async asyncData() {
let result = await $axios.$post('/api/test', { data: this.totalPrice })
},
computed: {
...mapGetters(["totalPrice"])
}
}
As you can see I want to access getter object in asyncData However I got
As indicated in the documentation...
Warning: You don't have access to the component instance through this inside asyncData because it is called before initiating the component.
Instead, use the context object provided
async asyncData ({ store }) {
const body = { data: store.getters.totalPrice }
const { data } = await $axios.$post('/api/test', body)
return data
}
Methods should be placed into methods to have the vue context:
export default {
methods : {
async asyncData() {
let result = await $axios.$post('/api/test', { data: this.totalPrice })
}
},
computed: {
...mapGetters(["totalPrice"])
}
}
If you want to do it onload use mounted (https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram)
export default {
async mounted() {
let result = await $axios.$post('/api/test', { data: this.totalPrice })
},
computed: {
...mapGetters(["totalPrice"])
}
}

How to check if JSON data is loaded

I use axios to fetch my JSON file en vuex for using the fetched data over multiple components.
The thing is that my page renders before all data is loaded.
The following works because I delayed the rendering by 2 seconds, without this timeout it would result in an error.
I would like to do this the proper way but am not sure how to do it.
STORE.JS
Vue.use(Vuex);
const store = new Vuex.Store({
state: {
poss: null
},
getters: {
NAME: state => {
return state.name
},
POSS: state => {
return state.poss
}
},
mutations: {
SET_POSS : (state,payload) => {
state.poss = payload
},
ADD_POSS : (state,payload) => {
state.poss.push(payload)
},
},
actions:{
GET_POSS : async (context,payload) => {
let { data } = await axios.get("json/poss.json")
context.commit('SET_POSS',data)
},
SAVE_POSS : async (context,payload) => {
let { data } = await axios.post("json/poss.json")
context.commit('ADD_POSS',payload)
}
}
});
COMPONENT.VUE
module.exports = {
mounted:function(){
var self = this;
setTimeout(function () {
self.mkPageload()
}, 2000);
},
methods: {
mkPageload: function(){
let positions = this.$store.getters.POSS.pos
Object.keys(positions).forEach(key => {
// rendering
}
}
}
}
The desired result is that the page is only rendered after all data from the JSON file has been loaded.
There are several ways to solve this.
You could use wait / async in your component.
async mounted () {
await userStore.getAll()
// access getter and render
},
Your could watch vuex variable like (could be done without async but I like to add them)
async mounted () {
await userStore.getAll()
},
computed: {
...mapGetters('users')
},
watch: {
users(newValue, oldValue) {
....
// render
}
}
dont'forget to import the mapGetters: https://vuex.vuejs.org/guide/getters.html