I was trying to target some children last night. I was trying to call el.focus()
on an input. My problem was that I was trying to do it from an instance method that fired from a button click, and the input was in a 3rd party library AND I was wrapping that in another component.
The solution for me was to put a ref
on my wrapper component.
For example, if you have markup like this:
<my-dropdown ref="myDropdown"></my-dropdown>
Inside my-dropdown
, you could put another ref
on one of its children:
<template>
<div>
<my-library-wrapper ref="libWrapper"></my-library-wrapper>
</div>
</template>
Inside my-library-wrapper
, you could import in a library from node_modules
that has refs on it. Most libraries put refs on things so you can use those to target them.
Now you could start to target our example components here with code like this:
console.log(this.$refs.myDropdown);
console.log(this.$refs.myDropdown.$refs);
console.log(this.$refs.myDropdown.$refs.libWrapper);
this.$refs.myDropdown.$refs.libWrapper.$refs.someThing.focus();
this.$refs.myDropdown.$refs.libWrapper.$refs.someThing.click();
At first glance, that might seem weird, but the benefit of doing this compared to stuff like this.$refs.myDropdown.$children[0].$children[1].focus();
is that refs
are much less brittle. If you or someone else adds <divs>
into the markup later, the code using refs
will not break because Vue is finding those ref-named elements by name, not by relative-distance.
My recommendation is to put ref="something"
on something and do console.log(this.$refs.something.$refs);
and take a look what you can see, and while you're doing that, do console.log(this.$refs.something);
and see what kind of other things are available in there-- stuff like $attrs
and $children
and $el
.
ref
attribute in the template like this:<details ref="detailsChild"></details>
. vuejs.org/v2/api/#ref – Walliw