In the last tutorial, we discussed that Components are meant to be reusable. In this tutorial, we will see a more practical example to understand the reusability concept, and we'll also cover how we can pass data into our component using props.

Let's say you are working on an AirBnB type house rental service and which shows a picture of the house along with a title and description.

Here is how the HTML markup looks

                
<div class="card mx-2" style="width: 18rem;">
        <img src="images/houses/house-1.jpg" class="card-img-top" alt="...">
        <div class="card-body">
             <h5 class="card-title">House #1</h5>
             <p class="card-text">Very Beautiful House</p>
             <a href="#" class="btn btn-primary">Book Now</a>
       </div>
 </div>
<div class="card mx-2" style="width: 18rem;">
          <img src="images/houses/house-2.jpg" class="card-img-top" alt="...">
           <div class="card-body">
                <h5 class="card-title">House # 2</h5>
                <p class="card-text">Country Side House</p>
                <a href="#" class="btn btn-primary">Book Now</a>
          </div>
</div>
<div class="card mx-2" style="width: 18rem;">
           <img src="images/houses/house-3.jpeg" class="card-img-top" alt="...">
           <div class="card-body">
            <h5 class="card-title">House # 3</h5>
             <p class="card-text">House with Swimming Pool</p>
            <a href="#" class="btn btn-primary">Book Now</a>
</div>

We have used the Bootstrap CSS library to help us with the basic design, and we have used Bootstrap Cards to display three properties on the page.
Here is how the output looks like.

Looks Great, let's now start optimizing it with VueJS.

Dynamic Data via Vue

The design looks great, but current data is static and there is a lot of repetition of Card markup in the code. let's create a new Vue Instance and define the data inside it, and loop through it to make the Card dynamic.

We have defined a new Vue Instance and also defined an array of properties.

    var app = new Vue({
       el: '#app' ,
       data:{
         properties: [
           {'title' : 'House # 1', 'description': 'Very Beautiful House', 'image' : 'house-1.jpg'},
           {'title' : 'House # 2', 'description': 'Country Side House', 'image' : 'house-2.jpg'},
           {'title' : 'House # 3', 'description': 'House with Swimming Pool', 'image' : 'house-3.jpeg'},
         ]
       }
    });

Inside our HTML, instead of static data, we can now loop through the list of properties and still get the same result on the webpage.

<div class="card mx-2" style="width: 18rem;" v-for="property in properties">
     <img :src="'images/houses/'+property.image" class="card-img-top" alt="...">
         <div class="card-body">
               <h5 class="card-title">{{property.title}}</h5>
               <p class="card-text">{{property.description}}</p>
                <a href="#" class="btn btn-primary">Book Now</a>
           </div>
</div>

Making Reusable Card Component

We have reduced the repetition, As a part of the Next step, what if we can make the markup shorter and more reusable so that it can be used anywhere in our application. Let's convert it into a reusable Vue component.

Currently, there are a lot of elements involved in displaying a single card element on the page. What if we can display the single property on the page with a simple HTML element like

<property-card></property-card>

Wouldn't it be great, with this we will have a reusable element and looking at the HTML markup we'll exactly know what this element is for!

Let's convert the card into a Vue component.

Vue.component('property-card',{
        template: `<div class="card mx-2" style="width: 18rem;">
                        <img src="images/houses/house-1.jpg" class="card-img-top" alt="...">
                        <div class="card-body">
                          <h5 class="card-title">Title</h5>
                          <p class="card-text">Description</p>
                          <a href="#" class="btn btn-primary">Book Now</a>
                        </div>
                    </div>`
    });

And in our HTML markup, we will loop over the array of properties to show the same number of property-card components.

<property-card v-for="property in properties"></property-card>

Since we have defined the dummy data inside the template of our property-card Component. We will get the same data in all the three cards.

Next, How do we get the data defined in root Vue Instance inside the component?

Passing Data to Child Component

Since our Component is out of scope for the root Vue instance it cannot directly access root instance's data property. To pass the data inside our component we'll have to make use of props.

Let's modify our component and define the required props.

      Vue.component('property-card',{
        template: `<div class="card mx-2" style="width: 18rem;">
                        <img :src="'images/houses/'+image" class="card-img-top" alt="...">
                        <div class="card-body">
                          <h5 class="card-title">{{title}}</h5>
                          <p class="card-text">{{description}}</p>
                          <a href="#" class="btn btn-primary">Book Now</a>
                        </div>
                    </div>`,

          props: ['title', 'description','image']
    });

We have defined three props named title, description, and image and also used them in our template.

To pass them to the component we can attach them as an attribute to the component element itself.

<property-card :title="property.title" :description="property.description" :image="property.image" v-for="property in properties"></property-card>

That's about it. We have managed to pass data from a parent component ( Root Vue instance in this example) to the child component (property-child in this example).

Comments