DEV Community

MaxwellBoecker
MaxwellBoecker

Posted on

Passing Data Between Components in Vue.js

Introduction

Building applications with Vue.js requires the composition of nested components. In this article, we will see how to pass data between these components to arrive at the desired functionality of our application. We will talk about two ways of passing data: we can pass data from parent to child by passing props, or we can use the $emit method in order to make data in a child component available to its parent.
Passing props, despite always being passed from parent to child, can actually allow for events to be triggered in the parent. We will investigate one such case when passing a function to a child component results in this very phenomenon.
The $emit method will not only make data available to a parent component, it can actually trigger a series of events in the parent component. We will see more about this below.

Meet The App

Let’s meet the app. We’ll be looking at a main page which contains data about a user's garden. When the user wishes to edit this info, a modal will be rendered which contains a form. The form will handle the user input and through a series of transactions, the data will be passed back to the main page in order to re-render the newly input data.
This is what our info bar looks like on the main page:
Alt Text

Changing Hands

As props, we will be passing a function down from the main page as well as the original data to be edited. The function takes a single parameter. The updated data from the submit will be passed in as the argument for this parameter. Because the function is called in the local scope of the edit form, we have access to the updated values, and they can be passed in as the argument to the function. However, since the function comes from the upper scope, when we call it, the values on the main page will be updated because the function is bound to that scope.

The component that calls our main-page function needs a way to receive the updated data from the form. For this we will use the $emit method. When the form submit button is clicked, the component will emit data. When this data is emitted, a function is triggered in the parent component which has this data automatically passed in as an argument. This function then updates the database as well as the data displayed on the main page. Lets take a look.

first we pass the props from the main page
GardenMain.vue

<editmodal
        :id="gardenId"
        :name="name"
        :lat="location.lat"
        :lng="location.lng"
        :width="gardenSize.width"
        :height="gardenSize.height"
        :updateMain="updateMain"
      ></editmodal>

The function updateMain looks like this:

updateMain: function (garden) {
      const { id, lat, lng, width, length, name } = garden.data;
      this.gardenSize = { width, height: length };
      this.name = name;
      this.location = { lat, lng };
    },

These props are being passed to the component EditModal, so let’s take a look at that component next
Since the props were passed as independent properties, we must prepare to receive them as such. Here is a look at how we register props in the receiving component:
EditModal.vue

export default {
  name: "EditModal",
  props: {
    id: {
      type: Number,
    },
    name: {
      type: String,
    },
    lat: {
      type: Number,
    },
    lng: {
      type: Number,
    },
    width: {
      type: Number,
    },
    height: {
      type: Number,
    },
    updateMain: {
      type: Function,
    },
  },

Each prop that is expected must be registered here along with the type expected.

Summarily we will pass these along to the next component, which is rendered in the modal, named Editor. Editor will in turn render the form and on submit, will capture the emitted data. This in turn calls the updateMain function. Our transaction will then be complete. Let’s take a look at two crucial elements in Editor, the template, where the form EditGarden is rendered, and the methods object in the script, where the submitEdit function is located.
Editor.vue

<template>
  <div>
    <EditGarden
      v-on:edit:garden="submitEdit"
      :id="this.id"
      :name="this.name"
      :lat="this.lat"
      :lng="this.lng"
      :width="this.width"
      :height="this.height"
    />
  </div>
</template>

methods: {
    submitEdit(info) {
      axios.put("/garden/gardenupdate", {
          id: this.id,
          info: info,
        })
        .then((garden) => {
          this.$emit("close");
          this.updateMain(garden);
        });
    },
  },

The first thing to note is the line of code

v-on:edit:garden="submitEdit"

in the template. edit:garden is a reference to the function found in the child component, handleSubmit. let's take a look.
EditGarden.vue

methods: {
    handleSubmit() {
      this.$emit("edit:garden", {
        name: this.gardenName,
        lat: this.latt,
        lng: this.long,
        width: this.wid,
        length: this.hei,
      });
    },
  },

Notice how the first argument to handleSubmit is "edit:garden". This is what the function is known as in Editor.vue. It is like the export name. The this.$emit method will make the values in the options object, the second argument to handleSubmit, available in the parent component whenever the handleSubmit function is called.

Notice also how in the v-on in the Editor.vue file we call the function submitEdit whenever the EditGarden child component emits data. In this way, the components are reactive and a change in one component can trigger a series of changes in others. The submitEdit function first makes an axios call to update the database. Then, if that has been successful, it calls its own $emit which takes only one argument, 'close'. This closes the modal in the parent component. Finally, it calls the updateMain function which was passed in from the main page. This updates the data in GardenMain, immediately re-rendering it to the page.
Here is our EditGarden form inside the modal
Alt Text

Here is the updated GardenMain
Alt Text

So, in recap, our data flow is:

  • props passed from GardenMain to EditModal
  • props passed from EditModal to Editor
  • props passed from Editor to EditGarden
  • data emitted from EditGarden to Editor(the user input)
  • data emitted from Editor to close the EditModal modal
  • updateMain function call in Editor immediately updates the data in GardenMain

Conclusion

Here we have demonstrated passing data every which way between parent and child components. Props was used to pass data from parent to child. $emit was used to emit data from child to parent. And a function passed down from the parent was called in a child which updated data in the parent.

Top comments (0)