I'm creating a shopping cart in VueJS. I have the cart icon in the header and my products in another component. I need to take the array of products inside of the header so i can print the length near to the cart icon. Here some code:
data: () => {
return {
cart: [],
products: [
{
name: "Margherita",
price: 5,
image: "https://www.scattidigusto.it/wp-content/uploads/2018/03/pizza-margherita-originale-Scatti-di-Gusto-1568x821.jpg"
},
{
name: "Marinara",
price: 4,
image: "https://wips.plug.it/cips/buonissimo.org/cms/2012/05/pizza-marinara-5.jpg"
},
{
name: "Diavola",
price: 6,
image: "https://www.coopshop.it/p/wp-content/uploads/2021/02/Salame_940x450.jpg"
}
]
}
You should store the list of products inside your Vuex store. From there the list will be available to each and every component in your application.
Related
Using Ant Design in Vue. In a Multi-select component, user is able to select and unselect associated objects. However, the existing tokens of preexisting associated objects should show the item.name, but instead show "undefined". It also does not show a checkmark next to existing objects in the select box. However, on submit, the "undefined" object is submitted correctly. New choices display within the select box correctly.
Here is the element in the view:
<a-form-item :label="`${contact.name}'s Outlets`"
:wrapperCol="{lg: {span: 20}, sm: {span: 24} }">
<a-select
mode="multiple"
v-model="contact.outlets"
style="width: 100%"
placeholder="Please select"
>
<a-select-option v-for="outlet in outlets" :key="outlet.name" :value="outlet.id">
{{ outlet.name }}
</a-select-option>
</a-select>
</a-form-item>
As indicated in comments, you used an object element in contact.outlets[] for the initial value of the select. However, the a-select's value properties are bound to each element's id, so no match is found:
<a-select-option
v-for="outlet in outlets"
:key="outlet.name"
:value="outlet.id" 👈 option value is an `id`
>
Solution
Instead of the object as initial value, use the object's id.
Composition API
export default {
setup() {
const outlets = reactive([
{ id: 1, name: 'Outlet A' },
{ id: 2, name: 'Outlet B' },
👇
{ id: 3, name: 'Outlet C' },
]); 👇
const contact = reactive({ name: 'John', outlets: [3] });
return { outlets, contact };
}
}
demo 1
Options API
export default {
data() {
const outlets = [
{ id: 1, name: 'Outlet A' },
{ id: 2, name: 'Outlet B' },
👇
{ id: 3, name: 'Outlet C' },
]; 👇
const contact = { name: 'John', outlets: [3] };
return { outlets, contact };
}
}
demo 2
I have a static site with Nuxt and content coming in from Strapi. I want to dynamically set the meta tags that are fetched asynchronously.
My site has an index page which passes the fetched data to index-web or index-mobile through props.
let pageMeta: any
const apiBase: string = 'https://strapi.xyz.com'
export default Vue.extend({
components: { Greeting, Showcase, Features, Footer },
props: {
data: Map,
pageMeta,
},
data() {
return {
loading: true,
}
},
metaInfo(): any {
return {
meta: [
{
hid: 'description',
name: 'description',
content: pageMeta.description,
},
{
hid: 'author',
name: 'author',
content: pageMeta.author,
},
],
}
},
})
The prop being passed in a JSON parsed object.
Having done this, the generated site does not have the meta tags added in.
As mentioned, you need to access the property with .this.
Anybody have experience with twitter cards and Vue, dynamically loading meta tags into the components? seems like it needs server side rendering, does anybody know a way to avoid coding all the server side rendering? I am loading the meta tag information from APIs in Vuex and using them within my vue-head meta function:
meta: function() {
return [
//twitter
{ name: "twitter:title", content: this.title, id: "t-title" },
{ name: "twitter:image", content: this.image, id: "t-image" },
{ name: "twitter:description", content: this.excerpt, id: "t-excerpt" },
{
name: "twitter:card",
content: "summary_large_image",
id: "t-card",
},
// Facebook / Open Graph
{ property: "og:title", content: this.title, id: "og-title" },
// with shorthand
{ p: "og:image", c: this.image, id: "og-image" },
];
},
When I navigate to my dynamic components trough navigation bar, vue-meta title, content, and schema are displayed correctly, but when I refresh the page or click on the external link I get a value of undefined.
i have stored title content and schema in the json file.
metaInfo() {
return {
title: `${this.seoTitle}`,
meta: [
{name: "robots", content: "index,follow"},
{
name: 'description',
content: `${this.seoContent}`
}
],
link: [
{rel: 'favicon', href: 'logo.ico'}
],
script: [{
type: 'application/ld+json',
json: this.markups
}]
}
},
data() {
return {
seoTitle: this.$route.params.title,
seoContent: this.$route.params.content,
markups:this.$route.params.markup,
}
}
<div class="landing-group-tours box" v-for="tour in boatTours" :key="tour.id">
<router-link
:to="{name: 'details', params:{id: tour.id, title: tour.seoTitle, content: tour.seoContent, markup:tour.markup}}">
</div>
<script>
import tours from '#/data/privateToursData.json'
export default{
data(){
return{
boatTours: tours
{
}
}
</script>
You should store the router parameters in the router itself or in the URL, not the link. What you do is passing objects internally when you click the link, but as you noticed, when you click the browser refresh button these params are gone.
What happens is that Vue will load the app and router, identify what components are responsible for rendering the route and pass the detected parameters from your router to the components. Hence losing any additional data you had in your link before.
Try to keep only the dynamic params in your router and load the rest in the component, based on app logic. I.e. Assuming your route looks like /details/:id, you should initialize the SEO params in your details component.
Typically these come from the backend and for faster access I would transform the array to literal object and access the record by key. I.e. transform the array from:
[
{ "id": 1008; "title": "title1", "content": "....", ... },
{ "id": 1009, "title": "..."... }
]
to
{
"1008": { title: "title1", content: "....", ... },
"1009": { .... }
}
and then store it in VueX (https://vuex.vuejs.org/guide/getters.html)
getters: {
// ...
getBoatTour: (state) => (id) => {
return state.boatTours[id] || { title: 'Not found', content: '......' }
}
}
data() {
const SEOdata = store.getters.getBoatTour(this.$route.params.id);
return {
seoTitle: SEOdata.title,
seoContent: SEOdata.content,
markups: SEOdata.markup,
}
}
I am building something with VueJS and I have some problem to select an item in a list:
Let's imagine the following VueJS component:
new Vue({
el: '#app',
data: {
list: [
{
id: 1,
title: 'My first Item',
selected: false
},
{
id: 2,
title: 'My second Item',
selected: false
}
]
}
})
With the selected property, I can apply a class or not to the item:
<div id="app">
<ul>
<li #click="item.selected = !item.selected" :class="item.selected ? 'active' : ''" v-for="item in list">{{ item.title }}</li>
</ul>
</div>
But now, let's imagine that I grab my data from an API, I still want to be able to select the items:
new Vue({
el: '#app',
data: {
list: []
},
created: function () {
// Let's imagine that this is an Ajax Call to a webservice
this.$set('list', [
{
id: 1,
title: 'My first Item'
},
{
id: 2,
title: 'My second Item'
}
])
}
})
Now, my html can't work anymore because the data has not a selected property.
So how could I do such a thing?
Here are two JsFiddle that explain the problem:
The working one
The non working one
Please read docs on vue lifecycle :
id prefer you set the list to be a computed property that always checks for returned items : ie ,
new Vue({
el: '#app',
data: {
list: []
},
computed: {
list (){
// Let's imagine that this is an Ajax Call to a webservice
let returned = [
{
id: 1,
title: 'My first Item'
},
{
id: 2,
title: 'My second Item'
}
]
return returned
}
}
})