Nuxt, Strapi can't get media url - vue.js

Could you guys please check my code and help me out.
I've uploaded some media to strapi and assigned them to each drink. Now I want to access that data with axios, I can get id, description, title etc. but I can not get URL from media.
Anyone could help please. Thanks!
NUXT:
<v-img
:src="'url(${http://localhost:1337}/drink.media.url)'"
></v-img>
<script>
async created() {
try {
const response = await axios.get("http://localhost:1337/drinks");
this.drinks = response.data;
} catch (error) {
this.error = error;
}
console.log(this.drinks)
},
};
</script>
JSON FROM POSTMAN
[
{
"id": 2,
"title": "Coca-Cola",
"description": null,
"price": 1,
"published_at": "2021-10-16T19:02:52.099Z",
"created_at": "2021-10-16T19:01:26.228Z",
"updated_at": "2021-10-16T19:02:52.124Z",
"unit": 250,
"media": [
"hash": "coca_cola_original_282x130_8baa6d1d20",
"ext": ".webp",
"mime": "image/webp",
"size": 37.01,
"url": "/uploads/coca_cola_original_282x130_8baa6d1d20.webp",
"previewUrl": null,
"provider": "local",
"provider_metadata": null,
"created_at": "2021-10-16T18:56:02.187Z",
"updated_at": "2021-10-16T18:56:02.206Z"
}
]
},
Thanks!

I don't know how you upload your images in strapi, but below I describe my method for uploading images of book covers in my strapi local-host and the way I access the image in my nuxt app. Maybe it is helpful for you to use it in your app.
First I made a new media field in my strapi "content-types builder" section and named it "bookCover". after that I upload my image in database for each book.
Second I used fetch() instead of created hook in my Nuxt app. below is the code of my Nuxt page script:
data() {
return {
books: [],
}
},
async fetch() {
this.books = await this.$axios.$get('http://localhost:1337/books');
}
Finally according to Nuxt documentation I used this code in my template part of my page:
<div>
<p v-if="$fetchState.pending">Fetching mountains...</p>
<p v-else-if="$fetchState.error">An error occurred :(</p>
<div v-else>
<!-- you must enter your index of drinks, for example here I access the first book image -->
<v-img max-width="250" :src="`http://localhost:1337${this.books[0].bookCover.url}`"></v-img>
</div>
</div>
I think if you use this method and use "fetch" hook and also modify the way you call src attribute in "v-img", you can access your image. Also notice that my variable names are different from your names and you must change them.

Related

How to make BigCommerce Category Description accessible to display within navigation

I am building a custom navigation for a BigCommerce site and need to display category descriptions within the navigation items in addition to name and url.
My navigation is being displayed via a component so I know I can't request Front Matter there, but as name and url are already accessible I thought the description would be as well..
Here is part of my navigation code where i'm trying to display the data. Any tips on how to achieve this would be appreciated!
{{#each children}}
<li class="navigation__submenu-item">
<a class="navigation__submenu-action has-subMenu"
href="{{url}}"
>
{{#if image}}
<img class="navigation__submenu-img" src="{{getImage image}}" alt="{{image.alt}}" />
{{/if}}
<div>{{name}}</div>
<small class="navigation__submenu-msg">{{description}}</small>
</a>
</li>
{{/each}}
You do indeed need to specify to show the description with Front Matter. Something that is not explained well in the BC documentation is that you can actually specify global Front Matter in the config.json file. Assuming you are developing local with the Stencil CLI, you can edit the config.json file. You will look for the "resources" object and append the following code to it:
"categories": {
"description": true
}
So, if your resources object looks like this (default Cornerstone):
"resources": {
"cart": false,
"bulk_discount_rates": false,
"shop_by_brand": {
"limit": 10
}
},
Change it to this:
"resources": {
"cart": false,
"bulk_discount_rates": false,
"shop_by_brand": {
"limit": 10
},
"categories": {
"description": true
}
},

Stripe is not defined in Nuxt

I want to add stripe elements to my nuxt js page However, I got an error
Stripe is not defined
I have inserted the <script src="https://js.stripe.com/v3/"></script> on my nuxt.config.js
Here's the code
head: {
title: process.env.npm_package_name || "",
script: [{ src: "https://js.stripe.com/v3/" }],
link: [
{ rel: "icon", type: "image/x-icon", href: "/favicon.ico" },
]
},
My payment page
<template>
<div>
<div ref="card"></div>
<button v-on:click="purchase">Purchase</button>
</div>
</template>
<script>
let stripe = Stripe("Key"),
elements = stripe.elements(),
card = undefined;
export default {
mounted: function() {
card = elements.create("card");
card.mount(this.$refs.card);
},
methods: {
async purchase() {
let result = await stripe.createToken(card);
}
}
};
</script>
I followed this tutorial and still can't fix it
https://alligator.io/vuejs/stripe-elements-vue-integration/
You are including stripe for into scripts, so it will be loaded in browser. But nuxt is SSR. And the code in your script section will be also executed on server. And on server there no stripe, so it wont work. You need to execute all your code that create Stripe in mounted hook, which is only executed on client

How to add structured data (json-ld) to Vue?

What’s the correct way to add json-ld to a vue app?
I’ve added some structured data but Google structured data testing tool does not detect the data at my url. However, if I view the source of url and paste into the testing tool it detects my data. What am missing?
One way you can add JSON-LD with VueJS is using v-html like in the example below.
You can find out more about structured data from Schema.org with VueJS in this article.
There is also this plugin on NPM that can help you do this.
<script>
export default {
data () {
const jsonld = {
"#context": "https://schema.org",
"#type": "BreadcrumbList",
"itemListElement": [{
"#type": "ListItem",
"position": 1,
"name": "Books",
"item": "https://example.com/books"
}, {
"#type": "ListItem",
"position": 2,
"name": "The Lord of the Rings",
"item": "https://example.com/books/the-lord-of-the-rings"
}]
}
return {
jsonld
}
}
}
</script>
<template>
<script v-html="jsonld", type="application/ld+json">
</template>

Is there a working solution to load custom HTML Elements in the vue-dropzone message area?

I've been working around my code using vue-js and vue-dropzone to handle drag-&-drop upload functionality to a site. I added ":useCustomSlot=true" to to the parent html-tag but the content i placed in the dropzone tag is not rendering on the DOM! Can you understand what the issue is.
the page is still rendering the default message from the vue-dropzone.
Here are the codes:
<vue-dropzone id="customdropzone"
ref="myVueDropzone"
:options="dropzoneOptions"
:useCustomSlot=true>
<div class="dropzone-custom-content">
<h3 class="dropzone-custom-title">Drag and drop to upload content!</h3>
<div class="subtitle">...or click to select a file from your computer</div>
</div>
</vue-dropzone>
And the Vue Instance:
var App = new Vue({
el:'#app',
data: {
...,
dropzoneOptions: {
url: './upload.php',
addRemoveLinks: true,
thumbnailWidth: 150,
maxFilesize: 3, // MB
maxFiles:1,
acceptedFiles: '.png,.jpg,.mp4',
headers: { "My-Awesome-Header": "header value" },
}
},
components: {
vueDropzone: vue2Dropzone
}
});
try :use-custom-slot="true" (kebab-case)

Rendering data in Vue

I'm trying to create a Card component in Vue that renders some data I pull from firebase. In React I'd pretty much just use map and render out a <Card /> component then go create the Card component separately. Something like this
anArray.map((item, index) => return <Card key={index} index={index} item={item}/>
That would give me the specific item and I could work off the data from there. I'm not sure how to accomplish the same type of thing in Vue. I've created a JSFiddle. The data and bootstrap is already pulled in. I store the data in an object. Is storing it in an object or an array preferred?
https://jsfiddle.net/agzLz554/
The data should be an array because you actually need render item list. If you store it in object, you need to extract key/value mapping, and flatten to array. Because you question actually has nothing to do with the parse, so i set the data directly into vue data.
There are 4 problems:
you should store data in array, not object
you should not set template attribute in vue instance, it's used for component, not the root instance
your card html code should live inside in #app, otherwise, it can't be recognize
your card code loop, should not set id='card', id should be unique
check this JSFiddle example, https://jsfiddle.net/seaify/najm1uer/
<script src="https://unpkg.com/vue#2.0.3/dist/vue.js"></script>
<script src="https://www.gstatic.com/firebasejs/3.4.1/firebase.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.5/css/bootstrap.min.css" integrity="sha384-AysaV+vQoT3kOAXZkl02PThvDr8HYKPZhNT5h/CXfBThSRXQ6jW5DO2ekP5ViFdi" crossorigin="anonymous">
<div id="app">
<div class="card" v-for="resource in resources">
<div class="card-header">
<!-- Author Name -->
</div>
<div class="card-block">
<h4 class="card-title">{{resource.title]}}<!-- Article Title --></h4>
<p class="card-text">{{resource.desc}}<!-- Article Description --></p>
Go somewhere
</div>
</div>
</div>
/**
* Created by chuck on 2/11/16.
*/
var vm = new Vue({
el: '#app',
data () {
return {
resources: [
{
"objectId": "-KVSES7sKx-kk31gPyiz",
"authorId": "3F14Sh3vCMXhRfZyxRPBPzn8Rdf2",
"authorImage": "https://lh3.googleusercontent.com/-5QsKgD8Li8k/AAAAAAAAAAI/AAAAAAAABbY/v-uLFhw6k8Q/photo.jpg",
"authorName": "Maxwell Gover",
"desc": "Other developers actually have to use the APIs you design. So don’t let those APIs suck.",
"quiz": [
{
"options": [
{
"isAnswer": true,
"text": "True"
},
{
"isAnswer": false,
"text": "False"
}
],
"text": "The more dependencies you have, the more potential problems it can cause in downstream consumer code"
},
{
"options": [
{
"isAnswer": true,
"text": "True"
},
{
"isAnswer": false,
"text": "False"
}
],
"text": "You should try to keep your code as self contained as possible."
}
],
"timesPassed": 0,
"title": "How to design APIs that don't suck",
"type": "article",
"url": "https://medium.freecodecamp.com/https-medium-com-anupcowkur-how-to-design-apis-that-dont-suck-922d864365c9#.my0qpwrp5"
},
{
"objectId": "-KVSXfEragBTcqcyMTAR",
"authorId": "3F14Sh3vCMXhRfZyxRPBPzn8Rdf2",
"authorImage": "https://lh3.googleusercontent.com/-5QsKgD8Li8k/AAAAAAAAAAI/AAAAAAAABbY/v-uLFhw6k8Q/photo.jpg",
"authorName": "Maxwell Gover",
"desc": "How to prioritize improving user experience",
"quiz": [
{
"options": [
{
"isAnswer": true,
"text": "True "
},
{
"isAnswer": false,
"text": "False"
}
],
"text": "No matter how clever a design is, it is rendered useless if it fails to be understood."
}
],
"timesPassed": 0,
"title": "7 Tips to Improve Your UX Strategy",
"type": "article",
"url": "https://uxdesign.cc/7-tips-to-improve-your-ux-strategy-5e39f5ff0a41#.n103o5inc"
}
]}
}
})
If you need to write code like <Card key={index} index={index} item={item}/>, all you need to do is just extract your card html code to a component's template.
Vue.component('card', {
template: '<div>A custom component!</div>'
})
In addition to seaify's answer, if you register card as a component and iterate via v-for
Vue.component('card', {...})
<card v-for="resource in resources">
...
</card>
then you have to take care of that you may have some performance issues because of the reactivity system. In Vue.js, initializing a component is a little bit expensive.
If you really need to iterate a component, you should use a functional component: https://vuejs.org/guide/render-function.html#Functional-Components
Iterating a normal component is about 6~10x slower than functional component on my computer. Here is a simple performance test, iterate a component 2000 times (about 400 ~ 600 ms):
(open dev console to see the result)
http://codepen.io/CodinCat/pen/yaGAWd?editors=1010
vs functional component (about 40 ~ 60 ms):
http://codepen.io/CodinCat/pen/XjowAm?editors=1010