Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to foward $refs in Vue

I have a component which should pass everything on to the child. I'm successfully passing $attrs and $listeners already:

<template>
  <el-form v-on="$listeners" v-bind="$attrs" :label-position="labelPosition">
    <slot />
  </el-form>
</template>

But I'm unsure how to also forward $refs like we can do in React, so that when using my component like this:

<el-form-responsive
  class="form"
  :model="formValues"
  status-icon
  :rules="rules"
  ref="form"
  label-width="auto"
  @submit.native.prevent="submitForm"
>

Then this.$refs.form is actually a reference to the child <el-form>.

I would rather do this transparently, as in you pass exactly the same props to el-form-responsive as you would to a el-form without needing to know that refs has to be passed in a special way.

like image 405
Dominic Avatar asked Oct 12 '19 16:10

Dominic


1 Answers

I don't think it is possible to directly mimic React's ref. A ref attribute in Vue is just a string which is used to register a child component reference to the parent's $refs object during the render function.

Here are the links to documentations doc & doc

So basically it's a kind of inverted logic.. instead of passing a ref to a child in Vue we get it from the child into the parent. So it's not really possible at this point to create a grandchild reference, which is what you need.

There are some workarounds though.

1. Quick dirty and not transparent but technically it would work: In the parent component, which uses your el-form-responsive, on mounted hook we could replace the original child reference with the grandchild ref.

Your el-form-responsive component. Template:

<el-form ref="elform">

A parent which uses your el-form-responsive. Template:

<el-form-responsive ref="form">

Script:

...
mounted () {
  this.$refs.form = this.$refs.form.$refs.elform
}

And after this this.$refs.form is actually a reference to the granchild <el-form>

2. This one would be more elaborate, but probably mach better then the first method:

In order to make the el-form-responsive component really transparent you could expose some of the methods and properties from the child el-form component to any potential parent. Something like this:

el-form-responsive. Template:

<el-form ref="elform">

Script:

export default {
  data: () => ({
    whatever: null
  }),
  mounted () {
    this.whatever = this.$refs.elform.whatever
  },
  methods: {
    submit () {
      this.$refs.elform.submit()
    }
  }
}

So then inside some parent el-form-responsive could be used like this:

<el-form-responsive ref="form">
...
mounted () {
  const formWhatever = this.$refs.form.whatever // actually `whatever` from `el-form`
  this.$refs.form.submit() // eventually calls submit on `el-form`  
},
like image 88
maxim Avatar answered Oct 28 '22 23:10

maxim