Do you recall the example where ‘Apple’ was written by all three components on the previous page? We can now use props to deliver data to our components, giving them varied information and a different appearance. To demonstrate “Apples,” “Pizza,” and “Rice,” let’s create a basic page.

The component tags are sent to a prop using our custom property ‘food-name’, which is created in the main application file App.vue:
App.vue:
<template>
<h1>Food</h1>
<food-item food-name="Apples"/>
<food-item food-name="Pizza"/>
<food-item food-name="Rice"/>
</template>
<script></script>
<style>
#app > div {
border: dashed black 1px;
display: inline-block;
width: 120px;
margin: 10px;
padding: 10px;
background-color: lightgreen;
}
</style>
Accessing Data within a Component
We use this new ‘props’ configuration option to accept the data given by App.vue via the ‘food-item’ property. In order for our component *.vue
file to be aware of the characteristics we got, we list them. After that, we may utilize the props anywhere we like, just as we would with a data property.
FoodItem.vue:
<script>
export default {
props: [
'foodName'
]
}
</script>
In the template tag, props attributes are written with a dash to separate words (kebab-case), but JavaScript does not allow this. Instead, we must write the attribute names in JavaScript using camel case, which Vue will immediately comprehend!
Lastly, here is how our example with the div components for “Apples,” “Pizza,” and “Rice” appears:
Example
App.vue:
<template>
<h1>Food</h1>
<food-item food-name="Apples"/>
<food-item food-name="Pizza"/>
<food-item food-name="Rice"/>
</template>
FoodItem.vue:
<template>
<div>
<h2>{{ foodName }}</h2>
</div>
</template>
<script>
export default {
props: [
'foodName'
]
}
</script>
<style></style>
Before we demonstrate how to provide various data types as props attributes to components, let’s add a description of each food type to our code and place the food div elements inside a Flexbox wrapper.
Example
App.vue:
<template>
<h1>Food</h1>
<div id="wrapper">
<food-item
food-name="Apples"
food-desc="Apples are a type of fruit that grow on trees."/>
<food-item
food-name="Pizza"
food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."/>
<food-item
food-name="Rice"
food-desc="Rice is a type of grain that people like to eat."/>
</div>
</template>
<script></script>
<style>
#wrapper {
display: flex;
flex-wrap: wrap;
}
#wrapper > div {
border: dashed black 1px;
margin: 10px;
padding: 10px;
background-color: lightgreen;
}
</style>
FoodItem.vue:
<template>
<div>
<h2>{{ foodName }}</h2>
<p>{{ foodDesc }}</p>
</div>
</template>
<script>
export default {
props: [
'foodName',
'foodDesc'
]
}
</script>
<style></style>
Props from Boolean
By passing props of various data kinds, we may accomplish a variety of tasks. Additionally, when components are built from App.vue, we can provide rules for how attributes are assigned.
'isFavorite'
is a new prop that should be added. This should be a boolean prop with a true or false value so that, if the dish is deemed a favorite, we can utilize it directly with v-show to display a favorite stamp tag.
If we wish to send props with a data type other than String, we need to specify v-bind:
before the attribute.
Here’s how we pass the App.vue boolean ‘isFavorite’ prop as a property called ‘is-favorite’:
App.vue:
<template>
<h1>Food</h1>
<p>My favorite food has a diploma image attached to it.</p>
<div id="wrapper">
<food-item
food-name="Apples"
food-desc="Apples are a type of fruit that grow on trees."
v-bind:is-favorite="true"/>
<food-item
food-name="Pizza"
food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."
v-bind:is-favorite="false"/>
<food-item
food-name="Rice"
food-desc="Rice is a type of grain that people like to eat."
v-bind:is-favorite="false"/>
</div>
</template>
FoodItem.vue gives us the boolean ‘isFavorite’ attribute, and if the food is deemed favorite, we display a favorite stamp:\
Example
FoodItem.vue:
<template>
<div>
<h2>
{{ foodName }}
<img src="/img_quality.svg" v-show="isFavorite">
</h2>
<p>{{ foodDesc }}</p>
</div>
</template>
<script>
export default {
props: ['foodName','foodDesc','isFavorite']
}
</script>
<style>
img {
height: 1.5em;
float: right;
}
</style>
Images: Open the aforementioned example, right-click on the image, select “Save Image As…”, and store it in the “public” folder of your project to make it work locally in the project on your computer.


Prop Definitions
We are unable to confirm if the ‘isFavorite’ argument is a boolean value or not in the aforementioned case because of the code inside FoodItem.vue. This may be facilitated by defining the data-type of the props we get, making them needed, and even creating validation methods to verify the props we receive.
Defining the props we get gives us alerts in the console if the rules we have established are breached, and it also acts as documentation for others if you work in a team.
Props Objects
To have it as a reference, we declare the props in an object in FoodItem.vue and comment out the way we specified them in an array. In addition to the prop name, we may provide each prop’s data type as follows:
FoodItem.vue:
<script>
export default {
// props: ['foodName','foodDesc','isFavorite']
props: {
foodName: String,
foodDesc: String,
isFavorite: Boolean
}
}
</script>
Props defined this manner make it easy for others to know what the component expects when they look within FoodItem.vue.
A warning similar to this appears in the console if a component is made from the parent element (in our example, App.vue) and given a prop with the incorrect data type:

These warnings are helpful in alerting us and others to the improper usage of a component and in identifying the issue so that it may be fixed.
Defining Required Inputs for Components
We must specify the prop as an object in order to inform Vue that it is necessary. Let’s need the prop ‘foodName’ in this way:
FoodItem.vue:
<script>
export default {
// props: ['foodName','foodDesc','isFavorite']
props: {
foodName: {
type: String,
required: true
},
foodDesc: String,
isFavorite: Boolean
}
}
</script>
A warning similar to this appears in the console if a component is made from the parent element (in our example, App.vue) and a necessary prop is not defined:

These warnings are helpful in alerting us and others to the improper usage of a component and in identifying the issue so that it may be fixed.
Default Variable Values
For a prop, we can set a default value.
In the ‘FoodItem’ component, let’s set the ‘foodDesc’ prop to its default value. Then, without defining the ‘foodDesc’ prop, let’s build an item for rice:
Example
App.vue:
<template>
<h1>Food</h1>
<p>My favorite food has a diploma image attached to it.</p>
<div id="wrapper">
<food-item
food-name="Apples"
food-desc="Apples are a type of fruit that grow on trees."
v-bind:is-favorite="true"/>
<food-item
food-name="Pizza"
food-desc="Pizza has a bread base with tomato sauce, cheese, and toppings on top."
v-bind:is-favorite="false"/>
<food-item
food-name="Rice"
food-desc="Rice is a type of grain that people like to eat."
v-bind:is-favorite="false"/>
</div>
</template>
FoodItem.vue:
<script>
export default {
props: {
foodName: {
type: String,
required: true
},
foodDesc: {
type: String,
required: false,
default: 'This is the default description.'
},
isFavorite: {
type: Boolean,
required: false,
default: false
}
}
}
</script>
Prop Validation with Functions
A validator function that determines whether or not the prop value is valid can also be defined.
These validator routines have to give back true or false. The prop value is deemed invalid when the validator returns false. When we run our page in development mode, an invalid prop value causes a warning to appear in the browser console. This warning is a helpful reminder to ensure that the components are used as intended.
Assume for the moment that we would like the food description to be between 20 and 50 characters long. To ensure that the length of the provided meal description is appropriate, we can provide a validator function.
FoodItem.vue:
<script>
export default {
props: {
foodName: {
type: String,
required: true
},
foodDesc: {
type: String,
required: false,
default: 'This is the default description.',
validator: function(value) {
if( 20<value.length && value.length<50 ) {
return true;
}
else {
return false;
}
}
},
isFavorite: {
type: Boolean,
required: false,
default: false
}
}
}
</script>
Note: Pizza’s meal description is 65 characters long, which is 15 characters greater than the validator function permits. If you apply the validator code above to your local project, you will receive a warning in development mode.

Altering Component Props
We are not permitted to alter the value of the prop received in the child element once a component has been formed in the parent element. Therefore, we are unable to modify the value of the ‘isFavorite’ attribute that we obtain from App.vue within FoodItem.vue. From the parent, in this example App.vue, the prop can only be read.
However, suppose that by pressing a button, we would like the user to be able to alter which foods are deemed favorites. The ‘isFavorite’ prop has to be changed right now, but we are unable to do so because it is read-only.
We are not allowed to change ‘isFavorite’. This will generate an error.
methods: {
toggleFavorite() {
this.isFavorite = !this.isFavorite;
}
}
This may be avoided by using the prop to initialize a new data value called “foodIsFavorite” inside FoodItem.vue in the manner described below:
data() {
return {
foodIsFavorite: this.isFavorite
}
}
The user can now toggle this new data value by adding the following method:
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
}
}
It is also necessary to modify the v-show in the image tag to rely on the new data property ‘foodIsFavorite’ and add a toggle button to every food item. Additionally, we reduced the props declaration to just an array in order to simplify our example.
Example
FoodItem.vue:
<template>
<div>
<h2>
{{ foodName }}
<img src="/img_quality.svg" v-show="foodIsFavorite">
</h2>
<p>{{ foodDesc }}</p>
<button v-on:click="toggleFavorite">Favorite</button>
</div>
</template>
<script>
export default {
props: ['foodName','foodDesc','isFavorite'],
data() {
return {
foodIsFavorite: this.isFavorite
}
},
methods: {
toggleFavorite() {
this.foodIsFavorite = !this.foodIsFavorite;
}
}
};
</script>
<style>
img {
height: 1.5em;
float: right;
}
</style>