Reputation: 8167
I have some component that wraps up an input:
<div class="some-component">
<input type="text" />
</div>
And I'm calling it like so:
<some-component v-on:click="dostuff" ref="thatcomponent"></some-component>
And then:
methods: {
dostuff(){
this.$refs.thatcomponent.$el.focus();
}
}
Which focuses the div, where I really want focus to be on the input. This example is my first use-case, but in general I want to pass all the events called on the component to a specific element within that component. I don't want to go poking around in the component for the element from the parent component.
Is there a Vue pattern for this?
Upvotes: 1
Views: 1849
Reputation: 582
I guess your best bet here is using ref attribute and $refs object. This section in Vuejs Docs might be useful.
Child Component
in template:
<div class="some-component">
<input ref="input" type="text" />
</div>
in script:
methods: {
...
focus() {
this.$refs.input.focus();
},
...
},
Parent Component
in template:
You need here to use the .native
modifier to listen directly to a native event on the root element.
<some-component v-on:click.native="dostuff" ref="thatcomponent"></some-component>
in script:
methods: {
...
dostuff() {
this.$refs.thatcomponent.focus();
},
...
}
Vuejs Docs
$refs are only populated after the component has been rendered, and they are not reactive. It is only meant as an escape hatch for direct child manipulation - you should avoid accessing $refs from within templates or computed properties.
Here is CodeSandBox example
I Hope this help.
Upvotes: 0
Reputation: 1601
Better approach is to add the focus method within the child-component
<div class="child-component">
<input type="text" ref="theInput" />
</div>
// child-component
methods: {
focus(){
this.$refs.theInput.focus();
}
}
<child-component v-on:click="dostuff" ref="childComponent"></child-component>
// parent-component
methods: {
dostuff(){
this.$refs.childComponent.focus();
}
}
In any case if you want to interact with the child-component's input element from parent-component (useful if you don't have control over the child-component
// parent-component
methods: {
dostuff(){
this.$refs.childComponent.$el.querySelector('input').focus();
}
}
Upvotes: 2
Reputation: 7160
I'm not aware of a Vue specific solution to this. You can however manually redirect an event from one element to another by dispatching a new event on the target element.
You will however need a reference to the target element as well as handling all event types manually (there is no wildcard event listener like foo.addEventListener("*", ...)
clicked(e) {
var target = document.querySelector("#target");
target.dispatchEvent(new event.constructor(e.type, e));
}
Basic example:
https://codesandbox.io/s/vue-template-76svb
It is a very unusual pattern though and one should carefully evaluate if this is the correct solution to the problem.
Upvotes: 1