Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting Specific Parent Component By Name in Vuejs

I need a reliable way to call the a parent component of n parents in vuejs. Looking for something more like closest('element') in jQuery where you don't have to specify how many parents or children there are, you only give it the name of the component you need and it will look it up for you recursivly untill it finds the right one.

I just wonder if there is something like: this.$find(component-name); or this.$closest(component-name);

I have read somewhere people are using $ref, but I don't think that's the right one for this use-case or is it ?

Instead of this.$parent.$parent which is obviously not very reliable, when you don't know how many parents there are.

Thanks,

like image 331
Eden Reich Avatar asked Oct 08 '18 18:10

Eden Reich


People also ask

How do I get a parent Vue?

You can download the ParentVUE app on your device. Search for "ParentVUE" on the App Store or Google Play and click download.

What is $root in Vuejs?

Accessing the Root Instance In every subcomponent of a new Vue instance, this root instance can be accessed with the $root property. For example, in this root instance: // The root Vue instance.

How do you access a root component from a child instance in Vue?

We can access the root instance of from a child component with the $root property. 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.

What is $parent in VUE JS?

How $parent is described in Vue? The $parent property, like $root, can be used for accessing the parent instance from a child. It provides direct access, making the application hard to test and debug.


1 Answers

You could use a while loop, iterating over all the parent components.

getComponent(componentName) {
  let component = null
  let parent = this.$parent
  while (parent && !component) {
    if (parent.$options.name === componentName) {
      component = parent
    }
    parent = parent.$parent
  }
  return component
},

Example:

mounted() {
  console.log(this.getComponent('App'))
},

Utility function (TS):

import Vue from 'vue'

/**
 * @name findParentComponentByName
 * @summary Find the Vue instance of the first parent component that matches the provided component name.
 *
 * @description The `findParentComponentByName()` method returns the Vue instance of the first parent component
 * that has a `name` component option that matches the provided component name.
 *
 * @param {Vue} vm - The children component Vue instance that is looking for the parent component Vue instance
 * @param {string} componentName - The parent component name
 * @returns {Vue|undefined} The parent component instance that matches the provided component name,
 * otherwise, undefined is returned
 *
 * @example
 * // Find `<App/>` component from `<Child/>`:
 * <App>
 *   <GrandParent>
 *     <Parent>
 *       <Child/>
 *     </Parent>
 *   </GrandParent>
 * </App>
 *
 * // Descendant component Vue instance
 * new Vue({
 *   name: 'Child',
 *
 *   created() {
 *     const app = findParentComponentByName(this, 'App')
 *     // => VueComponent {_uid: 1, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …}
 *  },
 * })
 */
export function findParentComponentByName(
  vm: Vue,
  componentName: string
): Vue | undefined {
  //
  //  Components tree:
  //  +---------------------+  \ return undefined, , <Child/> is not a descendant of <App/> \
  //  | <App>               |---> Return if component name option matches, otherwise
  //  |---------------------|    \ continue traversing the tree upwards \
  //  |   <GrandParent>     |-----> Return if component name option matches, otherwise
  //  |---------------------|      \ continue traversing the tree upwards \
  //  |     <Parent>        |-------> Return if component name option matches, otherwise
  //  |---------------------|        \ traverse the tree upwards \
  //  |       <Child/>      |---------> STARTING POINT, start looking for App component from here
  //  |---------------------|
  //  |     </Parent>       |
  //  |---------------------|
  //  |   </GrandParent>    |
  //  |---------------------|
  //  | </App>              |
  //  +---------------------+
  //

  let component: Vue | undefined
  let parent = vm.$parent

  while (parent && !component) {
    if (parent.$options.name === componentName) {
      component = parent
    }
    parent = parent.$parent
  }

  return component
}

Example:

// In consuming component
import { findParentComponentByName } from '@/utils'

// ...

mounted() {
  console.log(findParentComponentByName(this, 'App'))
},
like image 104
Ricky Avatar answered Oct 08 '22 01:10

Ricky