How to send props in Vue - vue.js

I am quite new in vue so I haven't understood the logic completely. My question is I have ticket and ticketlist components. So I am not on my ticket list component I am creating some tickets data and I want to show them according to the ticket component. To make it more clear here is my ticketlist component:
<template>
<section class="tickets">
<div class="container">
<div class="row">
<div class="col-12 col-md-3 mb-3">
<Ticket v-for="ticket in tickets" :key="ticket.id" :product="ticket"/>
</div>
</div>
</div>
</section>
</template>
<script>
import Ticket from './Ticket'
export default {
components: {
Ticket
},
data() {
return {
tickets: [
{
id: 0,
category: "Einzelkarte",
price: "€3,50",
tariff: [
"Wählen Sie eine Option",
"Erwachsene",
"Erwachsener erm.",
"Kinder / Jugendliche",
"Kinder / Jugendliche erm.",
],
available_amount: 23,
article_number: "2021.05.04-2673990197-1",
},
],
};
},
}
</script>
And also ticket component:
<template>
<widget type="ticket" class="--flex-column">
<div class="top --flex-column">
<div class="bandname -bold">Ghost Mice</div>
<div class="tourname">Home Tour</div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/199011/concert.png" alt="" />
<div class="deetz --flex-row-j!sb">
<div class="event --flex-column">
<div class="date">3rd March 2017</div>
<div class="location -bold">Bloomington, Indiana</div>
</div>
<div class="price --flex-column">
<div class="label">Price</div>
<div class="cost -bold">€{{ ticket.price }}</div>
</div>
</div>
</div>
<div class="rip"></div>
<div class="bottom --flex-row-j!sb">
<a class="btn button" href="#">ADD TO CART</a>
</div>
</widget>
</template>
<script>
export default {
props: ['ticket'],
}
</script>
<style scoped>
#import 'https://i.koya.io/flex/1.1.0.css';
*, ::after, ::before {
box-sizing: unset;
}
</style>
So, I am showing TicketList component in one of the page but the thing is it doesnt show anything. So I wonder how can I connect them together and show tickets data according to ticket component. I hope I am clear but if I am not I can answer you in the comments.

The probleme is the props name, you need to pass ticket as props and not product
...
<Ticket v-for="ticket in tickets" :key="ticket.id" :ticket="ticket"/>
...
or the contrary inside you Ticket component set :
props: ['product']

Related

Render content between component tags in specific div of component

I have the following vue component:
<template>
<div class="message__overlay">
<div class="message__overlay-content">
<div class="message__overlay-content-top">
<span class="message__overlay-close" #click="hideMessage"></span>
<h2>{{ title }}</h2>
<div v-html="content"></div>
</div>
<div class="message__overlay-content-bottom">
<a :href="`tel:${phoneNumber}`" class="message__overlay-link">Call Customer Services</a>
</div>
</div>
</div>
</template>
<script>
import SiteConstants from '../../Constants/site-constants.js';
import './styles.scss';
export default {
name: 'MessageOverlay',
props: {
title: {
default: '',
type: String,
},
phoneNumber: {
default: '',
type: String,
},
},
methods: {
hideMessage() {
document.body.classList.remove(SiteConstants.Classes.MessageOpen, SiteConstants.Classes.OverlayOpenWithPhoneLink);
},
}
};
</script>
Which I can use by registering and doing the following:
<message-overlay :title="'Notice!'" :phone-number="0123456789">
<p>To place orders, an agreement needs to be in place for new projects. </p>
<p>Please call our dedicated customer service team who will be happy to discuss and set this agreement up for future orders.</p>
</message-overlay>
How do I get the 2 paragraph tags (or any content between the message-overlay tags) in the child component to render in the div with v-html="content" of the parent component template?
You need to add a slot to your message-overlay component
<template>
<div class="message__overlay">
<div class="message__overlay-content">
<div class="message__overlay-content-top">
<span class="message__overlay-close" #click="hideMessage"></span>
<h2>{{ title }}</h2>
<div v-html="content">
<slot></slot>
</div>
</div>
<div class="message__overlay-content-bottom">
<a :href="`tel:${phoneNumber}`" class="message__overlay-link">Call Customer Services</a>
</div>
</div>
</div>
</template>
https://v2.vuejs.org/v2/guide/components-slots.html

Vue.js return and render templates

I have 2 templates in which the child one loop through images.I need to send it to the parent as array of templates and then loop them in the parent in order to avoid duplicates.How to accomplish that? below are the codes :
Products.vue (parent):
<template>
<div>
<div class="u-repeater u-repeater-1"><!--product_item-->
<div
class="u-align-center-lg u-align-center-sm u-align-center-xl u-align-center-xs u-container-style u-products-item u-repeater-item">
<ImageComponent></ImageComponent>
</div><!--/product_item--><!--product_item-->
</div>
</div>
</template>
ImageComponent.vue: (child)
<template>
<div class="u-container-layout u-similar-container u-container-layout-1">
<div v-for="n in Object.keys(products[0]).length" :key="n">
<img alt="" :src="products[n].image" data-image-width="510" data-image-height="340"
class="u-expanded-width-lg u-expanded-width-md u-expanded-width-sm u-expanded-width-xl u-image u-image-default u-product-control u-image-1">
<div
class="u-align-center u-container-style u-expanded-width-xs u-group u-opacity u-opacity-70 u-palette-5-light-2 u-group-1">
<div class="u-container-layout u-container-layout-2">
<h4 data-animation-name="fadeIn" data-animation-duration="1000" data-animation-delay="0"
data-animation-direction="Up" class="u-product-control u-text u-text-1 animated fadeInUp-played"
style="will-change: transform, opacity; animation-duration: 1000ms;">
{{ products[n].model }}
</h4>
<div class="u-align-left u-product-control u-product-price u-product-price-1">
<div class="u-price-wrapper u-spacing-10">
<div class="u-hide-price u-old-price">$12</div>
<div class="u-price" style="font-size: 1.25rem; font-weight: 700;">{{ products[n].price }}</div>
</div>
</div>
<a href="#"
class="u-align-center-xs u-border-active-none u-border-hover-none u-btn u-btn-rectangle u-button-style u-none u-product-control u-text-palette-1-base u-btn-1">Add
to Cart</a>
</div>
</div>
</div>
</div>
</template>
<script>
import {mapState} from "vuex";
export default {
name: "ImageComponent",
data(){
return{
items:[
]
}
},
computed: {
...mapState({
products: (state) => state.products,
}),
}
}
</script>
<style scoped>
.u-palette-5-light-2, .u-body.u-palette-5-light-2, .u-container-style.u-palette-5-light-2:before, .u-container-layout.u-palette-5-light-2:before, .u-table-alt-palette-5-light-2 tr:nth-child(even) {
color: #111111;
background-color: unset;
}
</style>
Remark: not all codes are written, just to give the main idea.
Thanks for help.

PrimeVue Toast displaying html tags

How can I implement displaying a link in a primevue toast message? I cannot use v-html directive and triple brackets do not work. Does anybody has another idea how to solve it?
A hacky way is to extends Toast component:
Here a codesandbox : https://codesandbox.io/s/extend-primevue-toast-o5o1c?file=/src/CustomToastMessage.vue
1. On your component
Import your custom toast component where you need to call this.$toast:
<template>
<div>
<CustomToast />
<CustomToast position="top-left" group="tl" />
<CustomToast position="bottom-left" group="bl" />
<CustomToast position="bottom-right" group="br" />
<div class="card">
<Button #click="test" label="test" />
</div>
</div>
</template>
<script>
import CustomToast from "./CustomToast.vue";
export default {
components: {
CustomToast,
},
data() {
return {
messages: [],
};
},
methods: {
test() {
this.$toast.add({
severity: "success",
summary: "Test",
detail: "<b>Test Bold</b>",
});
},
},
};
</script>
2. CustomToast.vue (extend primevue toast)
<template>
<Teleport to="body">
<div ref="container" :class="containerClass" v-bind="$attrs">
<transition-group name="p-toast-message" tag="div" #enter="onEnter">
<CustomToastMessage
v-for="msg of messages"
:key="msg.id"
:message="msg"
#close="remove($event)"
/>
</transition-group>
</div>
</Teleport>
</template>
<script>
import Toast from "primevue/toast/Toast.vue";
import CustomToastMessage from "./CustomToastMessage.vue";
export default {
extends: Toast,
components: {
CustomToastMessage,
},
};
</script>
3. CustomToastMessage (extend primevue toastmessage)
Add v-html where you want to have html
<template>
<div
:class="containerClass"
role="alert"
aria-live="assertive"
aria-atomic="true"
>
<div class="p-toast-message-content">
<span :class="iconClass"></span>
<div class="p-toast-message-text">
<span class="p-toast-summary">{{ message.summary }}</span>
<div class="p-toast-detail" v-html="message.detail"></div>
</div>
<button
class="p-toast-icon-close p-link"
#click="onCloseClick"
v-if="message.closable !== false"
type="button"
v-ripple
>
<span class="p-toast-icon-close-icon pi pi-times"></span>
</button>
</div>
</div>
</template>
<script>
import ToastMessage from "primevue/toast/ToastMessage.vue";
export default {
extends: ToastMessage,
};
</script>
There is an easiest solution.
Just implement your own template.
Example:
<Toast :position="toastPosition">
<template #message="slotProps">
<span :class="iconClass"></span>
<div class="p-toast-message-text">
<span class="p-toast-summary">{{slotProps.message.summary}}</span>
<div class="p-toast-detail" v-html="slotProps.message.detail" />
</div>
</template>
</Toast>

How to transfer data between components (siblings) Vue?

In the HeaderComponent method 'clickPrices' is called on click
<template>
<header>
<div class="d-flex flex-column flex-md-row align-items-center p-3 px-md-4 mb-3 bg-white border-bottom shadow-sm">
<h5 class="my-0 mr-md-auto font-weight-normal">Company name</h5>
<nav class="my-2 my-md-0 mr-md-3">
<a class="p-2 text-dark" href="#">Features</a>
<a class="p-2 text-dark">Enterprise</a>
<a class="p-2 text-dark" #click="clickPrices()">Get pricing</a>
</nav>
<a class="btn btn-outline-primary " href="#">Sign up</a>
</div>
</header>
</template>
<script>
export default {
name: "HeaderComponent",
methods: {
clickPrices() {
...
},
},
}
</script>
<style scoped>
</style>
and there is a Pricing Component in which I make a request to the server in the method 'getPricing'
<template>
<div class="wrap-pricing">
<div class="pricing-header px-3 py-3 pt-md-5 pb-md-4 mx-auto text-center">
<h1 class="display-4">Pricing</h1>
<p class="lead">Quickly build an effective pricing table for your potential customers with this Bootstrap example. It’s built with default Bootstrap components and utilities with little customization.</p>
</div>
<div class="container">
<div class="card-deck mb-3 text-center">
<div class="card mb-4 shadow-sm">
<div class="card-header">
<h4 class="my-0 font-weight-normal">Lorem</h4>
</div>
<div class="card-body">
<h1 class="card-title pricing-card-title">$10 <small class="text-muted">/ mo</small></h1>
<ul class="list-unstyled mt-3 mb-4">
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
<li>Lorem</li>
</ul>
<button type="button" class="btn btn-lg btn-block"></button>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import router from '../routes.js';
import { axios } from 'axios';
export default {
name: "PriceComponent",
methods: {
getPricing() {
axios.get('api/pricing').then((response) => {
//some actions
router.push('prices');
});
},
},
}
</script>
<style scoped>
</style>
How should I process the result of the 'сlickPrices' HeaderComponent method?
Or am I waiting for your ways, how can I get data in another by clicking in one component
You can emit an event and let the parent component handle the fetching and pass the data as props to the child component.
Or another way is to directly listen to the event as follows
Component 1:
this.$root.$emit('clickPrices', data);
Component 2:
mounted() {
this.$root.$on('clickPrices', data => {
this.getPricing();
});
}
Check out the answer by #alex
Since you are using 2 independent components (one is not included in the other), you cannot pass props
Things you can do -
Instead of fetching all the prices on click, just create a created hook like so, which will fetch all the pricing details whenever your component is created -
created () {
this.getPricing()
},
methods: {
getPricing() {
axios.get('api/pricing').then((response) => {
//some actions
router.push('prices');
});
},
},
Use State and when a user clicks on the button, pricing details are fetched and added in the state. And you can just use the state anywhere in your application like so -
this.$store.state.prices
Let me know if it works, if not we will find some other solution for you!

Vue JS Component reattach or Cache

VueJS component doesn't get cached or atleast reattached after navigation. On refresh or launch everything gets attached and rendered well but after navigating to another page then back. The First Component - Carousel - component in my case doesn't get rendered but the API call is made.
<template>
<div class="rel">
<div id="homeCarousel" class="owl-carousel owl-slider">
<div class="item" v-for="product in featured">
<div class="bg-holder top-area-half" >
<div class="bg-mask-lighten"></div>
<img class="bg-img" v-bind:src="product.feature_image_url">
<div class="hero-caption">
<div class="container">
<h3 class="hero-title">{{product.feature_title}}</h3>
<p class="hero-subtitle">{{product.feature_subtitle}}</p>
<a class="btn btn-white btn-ghost btn-lg hero-btn" href="#">Shop now</a>
</div>
</div>
</div>
</div>
</div>
<div id="hero-slider-nav" class="hero-slider-nav">
<div class="container">
<div class="pull-right"></div>
</div>
</div>
</div>
</template>
<style>
</style>
<script>
export default{
data(){
return{
featured:[]
}
},
ready(){
},
mounted(){
this.getFeaturedProducts();
},
components:{
},
methods: {
getFeaturedProducts: function () {
Vue.http.get('/api/product/filter/featured=1').then(
(response) => {
this.featured = response.body;
}
)
}
}
}
</script>
`
<template>
<div class="global-wrapper clearfix ">
<keep-alive>
<Carousel></Carousel>
</keep-alive>
//The rest of the code which is just importing the Component
I found out what i was doing wrong. I had a separate JS/JQuery file and on the document ready i was initializing an owl carousel by id #('homeCarousel').owlCarousel({}) . What worked was, since i had already bootstrapped owl carousel -> on the mounted lifecycle callback i was now targeting the element and making it an owl carousel.