Tushar Arora
Tushar Arora

Reputation: 1146

Vue - How to pass parent ref to child as a prop?

I am trying to pass current component's ref to a child component like this:

<template>
    <div class="screen" ref="screen">
        <child-component :screenRef="screenRef">
        </child-component>
    </div>
</template>


<script>
    const Parent = {
        name: 'parent',
        data: {
            screenRef: {}
        },
        mounted() {
            this.screenRef = this.$refs['screen']
        }
    }
</script>

Since Vue.js types don't support HTMLDivElement, I am getting an error in child component when I define screenRef as a prop.

const ChildComponent = {
  name: 'child',
  props: {
    screen: {
      type: HTMLDivElement,
      default: {}
    }
  }
}

Could someone please tell the correct way to do this?

Upvotes: 31

Views: 59158

Answers (5)

Sasha
Sasha

Reputation: 97

This is a common issue when e.g. implementing infinite scroll, where you need a parent container's ref to set up an IntersectionObserver inside a child component.

This should also work: pass a getScreenRef function that returns the ref and invoke it inside the child's mounted method:

<template>
    <div class="screen" ref="screen">
        <child-component :getScreenRef="() => $refs['screen']">
        </child-component>
    </div>
</template>


<script>
    const Parent = {
        name: 'parent',
    }
</script>


const ChildComponent = {
  name: 'child',
  props: {
    getScreenRef: {
      type: Function,
      default: () => ({})
    }
  },
  mounted() {
    // by the time the mounted method is called, screen ref will be available
    const screenRef = this.getScreenRef();
    ...
  }
}

Upvotes: 3

Valentine Shi
Valentine Shi

Reputation: 7800

You do all the things correct. Just do not declare the required type for the screen prop in the child component. The following props: {screen: {default: {}}} will do the trick.

As side notes:

  • The mounted hook is the correct place to assign the $refs elements to $data items as the former is not defined at created hook.

  • Vue has type: Object that still would work well for your screen prop type validation if you want to apply the props type validation.

  • If you by chance would want to assign the default object value other than the empty {} you have to assign it via function (unlike non-object data types):

    default: function () {
        return {a: 1, b: 2}
    }
    

Upvotes: 5

scorpion
scorpion

Reputation: 719

You can change default to null too and remove type. In my case I had to pass ref from sibling.

const ChildComponent = {
  name: 'child',
  props: {
    screen: {
      default: null
    }
  }
}

Upvotes: 0

Andrii
Andrii

Reputation: 166

Just try to access parent from child component via:

this.$parent

or

this.$el.parent

or use inheritAttrs option in child component for nontransparent pass of attributes from parent to child:

const ChildComponent = {
  inheritAttrs: true,
  name: 'child',
  props: {
    screen: {
      type: HTMLDivElement,
      default: {}
    }
  }
}

Upvotes: 13

Canor
Canor

Reputation: 919

If you need data from different component just pass it with props.

Or if you need this data in multiple components try Vuex:

https://vuex.vuejs.org/guide/

Upvotes: 2

Related Questions