Categories
JavaScript Vue

Vue.js Components — Parent, Child and Root

Spread the love

In this article, we’ll look at how to access various parts of a parent, child, or root component. Also, we look at dependency inject in Vue.js

Element & Component Access

Sometimes we have to access other components from a given component. However, it’s a bad idea to do this often since it gets messy fast.

Accessing the Root Instance

We can access the root instance of from a child component with the $root property.

For example, we can access the root Vue instance’s foo property as follows:

src/index.js :

Vue.component("foo", {  
  template: `<p>{{rootFoo}}</p>`,  
  computed: {  
    rootFoo() {  
      return this.$root.foo;  
    }  
  }  
});

new Vue({  
  el: "#app",  
  data: {  
    foo: "bar"  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <foo></foo>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

The code above created a rootFoo computed property from the root Vue instance’s foo component and displayed it inside the foo component.

So we get foo displayed.

The data returned from $root can also be set and its methods can so be called.

So we can write:

this.$root.foo = 2

or:

this.$root.baz()

from any subcomponent in addition to accessing the properties’ values.

Accessing the Parent Component Instance

Similar to $root , we can access the parent component’s properties with the $parent property from a child component.

This shouldn’t be used frequently because it’s hard to trace when the parent’s data was set, so we should pass in props to the child instead of accessing the $parent property directly.

For example, we can use it as follows:

src/index.js :

Vue.component("child", {  
  template: `<p>{{parentFoo}}</p>`,  
  computed: {  
    parentFoo() {  
      return this.$parent.foo;  
    }  
  }  
});

Vue.component("parent", {  
  data() {  
    return {  
      foo: "bar"  
    };  
  },  
  template: `  
    <p><slot></slot></p>  
  `  
});

new Vue({  
  el: "#app"  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <parent>  
        <child></child>  
      </parent>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we accessed the parent component’s foo property from the child component by using this.$parent in the computed property parentFoo. So, we get bar displayed on the screen.

Accessing Child Component Instances & Child Elements

We can access a child component directly in JavaScript. To do this, we can add a ref attribute to the child component and assign a name as the value.

Then we can use this.$refs.name to access the component where name is the name that we set.

For example, we can use it as follows:

src/index.js :

new Vue({  
  el: "#app",  
  mounted() {  
    this.$refs.input.focus();  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <input ref="input" />  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the example above, we added a ref with name input in the template and then we accessed the input element with:

this.$refs.input

And then called focus on it in the mounted hook.

This lets us focus the input as soon as the input element has loaded.

We can also access a child component’s methods as follows:

src/index.js :

Vue.component("base-input", {  
  methods: {  
    focus() {  
      this.$refs.input.focus();  
    }  
  },  
  template: `<input ref='input' />`  
});

new Vue({  
  el: "#app",  
  mounted() {  
    this.$refs.baseInput.focus();  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <base-input ref="baseInput"></base-input>  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, our root Vue instance called base-input ‘s focus method when it’s mounted.

Therefore, we see that the input is in focus when base-input loaded.

Dependency Injection

To prevent accessing the parent component and root Vue instance directly, we can use dependency injection to get the component that we want to get.

We can use it as follows:

src/index.js :

Vue.component("foo-button", {  
  methods: {},  
  inject: ["toggleFoo"],  
  template: `<button @click='toggleFoo'>Toggle Foo</button>`  
});

new Vue({  
  el: "#app",  
  data: {  
    foo: ""  
  },  
  provide() {  
    return {  
      toggleFoo: this.toggleFoo  
    };  
  },  
  methods: {  
    toggleFoo() {  
      this.foo = this.foo === "foo" ? "" : "foo";  
    }  
  }  
});

index.html :

<!DOCTYPE html>  
<html>  
  <head>  
    <title>App</title>  
    <meta charset="UTF-8" />  
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>  
  </head>  
  <body>  
    <div id="app">  
      <foo-button></foo-button>  
      {{foo}}  
    </div>  
    <script src="src/index.js"></script>  
  </body>  
</html>

In the code above, we added the provide method to return an object with the items that we want to make available to child components.

We made the toggleFoo method from the root Vue instance available to our foo-button component.

Then in the foo-button component, we injected the toggleFoo method from the parent to foo-button and then we call it when click events are triggered on the button.

We included foo-button in the template as usual.

In the end, we should see that we toggle the word foo on the screen when we click on the button.

Conclusion

We can access the root Vue instance with $root , and the parent component with $parent .

To access a child component from a parent, we can assign a ref with a name to the child component and then use this.$refs to access it.

These properties shouldn’t be used too often because they create a mess fast.

To keep accessing external components clean and traceable, we can use dependency injection by defining the provide method to expose certain parts of a component and use inject to get the provided parts.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *