Props & Dynamic Styles
Passing data to components via props
Our project currently repeats the Event.vue
component for each event we have stored. This will repeat the same event for each of the six array items in the browser. The reason each event is the same is because this is the HTML we have set up in the Event.vue
component:
<template>
<article>
<div class="event_data">
<h3 class="event_name">Graduation</h3>
<p class="event_details">Party time!!!</p>
</div>
<div class="event_countdown">
<div class="remove_btn_wrapper">
<button class="remove_btn">❌</button>
</div>
<div>
<p class="days_left">56</p>
<small>days left</small>
</div>
</div>
</article>
</template>
We can pass the correct data from each event to the component using props.
Props are Vue's way of passing data from parent to child components. They create a one-way data flow where parent components can send data down to their children, but children can not directly modify the data they receive. In the App.vue
, pass in the name
and details
props as attributes to the <Event>
:
<Event
v-for="event in eventData"
:key="event.id"
:name="event.name"
:details="event.details"
/>
:
is shorthand forv-bind
, telling Vue to evaluate the expression as JavaScript.:name
binds the event's name to a prop calledname
in the child component.:details
binds the event's details to a prop calleddetails
in the child component.- The right side (
event.name
,event.details
) references data from ourv-for
loop. - Without the colon, Vue would treat
event.name
as a literal string instead of a JavaScript expression.
Defining props in a component
We then need to declare which props are to be received in the component using defineProps()
, add this to the Event.vue
:
<script setup>
defineProps({
name: {
type: String,
required: true,
},
details: {
type: String,
required: true,
},
});
</script>
Using defineProps()
allows for setting up validation and requirements:
type
: The expected data type of the prop (String, Number, Boolean, Array, etc.).required
: Whether the prop must be provided.default
: A default/fallback value if no prop is received.validator
: A function to check if prop values are valid.
Rendering props in a template
These props are now available to use in the <template>
section using interpolation ({{ }}
). The current values always remain the same each time we use the component:
<template>
<article>
<div class="event_data">
<h3 class="event_name">Graduation</h3>
<p class="event_details">Party time!!!</p>
Update the event name and details with our dynamic props:
<template>
<article>
<div class="event_data">
<h3 class="event_name">{{ name }}</h3>
<p class="event_details">{{ details }}</p>
This double curly brace syntax is used to pass dynamic data to our HTML, similar to using a JavaScript variable. Both {{ name }}
and {{ details }}
will be replaced with the actual text of the prop passed to the component (Graduation, Holidays, etc).
Vue.js style bindings
The events also have a CSS background
property available:
{
id: 1,
name: "Graduation",
details: "wooohoo!!!",
date: "2027-09-25",
background: "linear-gradient(135deg, #FF416C, #FF4B2B)",
},
We can also pass this as a prop and use it to make the color of each event unique. In the App.vue
, update the props to also pass the background
:
<Event
v-for="event in eventData"
:key="event.id"
:name="event.name"
:details="event.details"
:background="event.background"
/>
Add this to defineProps()
in the Event component:
<script setup>
defineProps({
name: {
type: String,
required: true,
},
details: {
type: String,
required: true,
},
background: {
type: String,
required: true,
},
});
</script>
Then update the <article>
to include the inline styles:
<template>
<article :style="{ background }">
:style
is a Vue's directive for binding inline styles with dynamic data. The binding accepts a JavaScript object.{ background }
is shorthand for{ background: background }
when prop name matches CSS property.- Multiple styles can be added:
:style="{ background, color: textColor, fontSize: '16px' }"
- Vue automatically adds vendor prefixes when required.
With this update we can also remove the CSS background
property:
<style scoped>
article {
display: flex;
align-items: center;
/* background: linear-gradient(135deg, #2c3e50, #3498db); */