Stopbyte

How To Pass Data To A Child Component In Vuejs?

1-intro:

Javascript frameworks use a useful concept of “Components”.
download
Components are reusable instances with a name and props and they are used to extend basic HTML elements to encapsulate reusable code.

In Vuejs components are reusable Vue instances, they accept the same options as new Vue, such as data to store your data, computed to define cached-based functions that run only once, watch to watch your data and interact with them, methods to define your functions that accept arguments, and lifecycle hooks. The only exceptions are a few root-specific options like el.

Unless you’re creating your entire Vue app in one component (which wouldn’t make any sense), you’re going to encounter situations where you need to share data between components.

data can be passed either UP from the child to Parent or DOWN from the parent to child (our goal in this topic).

download (1)


You can see this Topic about passing data between all Vue components (UP & DOWN):


2- How To Pass Data “Down” from parent to child?

There are many techniques used by developers here are the effective ones:

a- Passing Data Using Props:

image-7

Vue provides props as some custom attributes you can register on any component. The way it works is that you define your data on the parent component and give it a value, then you go to the child component that needs that data and pass the value to a prop attribute so the data becomes a property in the child component.

In the end, you end up with a custom component the accepts arguments coming straight from the parent.

Let’s see this Example:

#Child component

    Vue.component('child-component', { 
      props: ['title'], 
      template: '<h3>{{ title }}</h3>' 
    })

In this example, we define a prop named title and use it in the components’ template.
then you specify what value it should take in the parent component (App.vue in this case) this way:

<child-component title="My journey with Vue"></child-component>

Warning:
for Dynamic binding you have to use the v-bind directive in the parent component:

<child-component v-bind:title="My journey with Vue"></child-component>

or:

<child-component :title="My journey with Vue"></child-component>

In other apps you’ll likely have an array of titles (or any other kind of data) :

    new Vue({
      el: '#app',
      data: {
        titles: [
          { id: 1, title: 'My journey with Vue' },
          { id: 2, title: 'Blogging with Vue' },
          { id: 3, title: 'Why Vue is so fun' }
        ]
      }
    })

then you will have to use the v-for to iterate through your titles array.

 <child-component
      v-for="title in titles"
      v-bind:key="titles.id"
      v-bind:title="titles.title"
></child-component>

the result would be something Like this:
image

→Strongly typed Props:

In some cases, you may want your component to only receive the exact data type you want it to receive.
Maybe you did not know but Vue can actually make props very strict and strongly typed.
Example:

<script>
export default {
  name: 'Test',
  props: {
    artists: {
      type: Array
    }
  }
}
</script> 

Here we made sure that it is only Arrays that will be passed down to my component

b- Passing Data Using $attrs (New in Vuejs):

$attrs
Type:

{ [key: string]: string }

Vue introduced $attrs as a way to bind all attributes except for class and style attributes.

By using $attrs you will be able to pass any attributes to whatever element you choose withing the child component. Here is an example:

Use "inhertiAttrs: false", inside your components’ script.

Child:

<template>
  <div class="InputComponent">
    <input v-model="model" type="text" v-bind="$attrs" />
  </div>
</template>

<script>
export default {
  name: 'InputComponent',
  inheritAttrs: false,
  data() {
    return {
      model: ''
    }
  }
}
</script>

Let’s say we want to pass an id and a data-tracking attributes from the parent.

Parent:

<child-component data-tracking="name" id="name"></child-component>

injecting and binding $attrs in the input will allow us to render the attributes above to it.
and the results after compiling would be as follows:

<div class="InputComponent">
    <input type="text" data-tracking="name" id="name" /> // attributes directly rendered.
</div> 

c- How to pass Data Variables directly from the child to the Parent:

parent component:

    <Child :parentData="{msg: 'xxx'}"></Child>

child component:

<template>
    <div>
        <h1>{{msg}}</h1>
    </div>
</template> 

now if you open your Vue Dev tools you will find in the parent component the attribute $attrs is added with this object within:

parentData={msg: 'xxx'}

image

check this Question for more How to pass data between Vuejs components effectively?
or visit Vue documentation to learn more about it here: $attrs

3- Advanced ways for Large SPA (“simple store” & “Vuex”)

Note: you can use more advanced ways to organize your work.
In case of very complicated work or deeply nested components use one of these two:

  • Vuex: Vuex is a state management pattern + library for Vue.js applications. it helps you handle Medium-to-large-scale Single page application and helps you simplify and keep track of your deeply nested Components.
    → Learn more about Vuex here: What Is Vuex And How Does It Work?

  • Simple State Management: using the same concept as Vuex it gives you access to a store pattern where you can store and handle your SPA. Since all components can share their state by identity, this store can handle all these components and their state in one singleton. emphasized text

4 Likes