Trigger the .focus() method on a neighboring VueJS Component

I am facing an issue with two independent components in my Vue instance. I have a select component and an input component, both of which are siblings. I need to trigger a focus event on the input component when the select component is changed.

Since both components are created from templates, using the ref attribute is not an option according to the Vue documentation https://v2.vuejs.org/v2/guide/components.html#Child-Component-Refs

Any suggestions on how I can achieve this? I have provided a simple example in this codepen - https://codepen.io/anon/pen/MVmLVZ

HTML

<div id='my-app'>
  <some-select></some-select>
  <some-input></some-input>
</div>
<script type="text/x-template" id="vueTemplate-some-select">
  <select @change="doStuff">
    <option value='1'>Value 1</option>
    <option value='2'>Value 2</option>
  </select>
</script>
<script type="text/x-template" id="vueTemplate-some-input">
  <input ref='text-some-input' type='text' value='Some Value'/>
</script>
 

Vue Code

  Vue.component('some-input', {
    template: `#vueTemplate-some-input`
  });

  Vue.component('some-select', {
       methods: {
            doStuff: function() {
              // Do some stuff
              //TODO: Now focus on input text field
              //this.$refs['text-some-input'].focus(); // Cant use refs, refs is empty
            }
        },
        template: `#vueTemplate-some-select`
    });

  var app = new Vue({
        el: '#my-app'
    });

Answer №1

When considering how to implement a behavior like this, it's important to understand the reasons behind it. If the selected value holds significance beyond just the select component, it should be managed by the parent component. One approach could involve passing the value to the input component and using a watcher to detect changes and set focus accordingly.

A possible solution might involve the following code snippet:

Vue.component("some-input", {
  template: `#vueTemplate-some-input`,
  props: ['watchValue'],
  watch: {
    watchValue() {
      this.$refs['text-some-input'].focus();
    }
  }
});

Vue.component("some-select", {
  props: ['value'],
  methods: {
    doStuff: function(event) {
      this.$emit('input', event.target.value);
    }
  },
  template: `#vueTemplate-some-select`
});

var app = new Vue({
  el: "#my-app",
  data: {
    selectedValue: null
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id='my-app'>
  <some-select v-model="selectedValue"></some-select>
  <some-input :watch-value="selectedValue"></some-input>
  <div>Selected: {{selectedValue}}</div>
</div>
<script type="text/x-template" id="vueTemplate-some-select">
  <select :value="value" @change="doStuff">
    <option value='1'>Value 1</option>
    <option value='2'>Value 2</option>
  </select>
</script>
<script type="text/x-template" id="vueTemplate-some-input">
  <input ref='text-some-input' type='text' value='Some Value' />
</script>

On the other hand, if the focus should be set specifically when the select component is changed, an event bus can be employed to handle communication between the components without direct coupling. Here is a potential implementation:

Vue.component("some-input", {
  template: `#vueTemplate-some-input`,
  props: ['changeBus'],
  mounted() {
    this.changeBus.$on('change', () => this.$refs['text-some-input'].focus());
  }
});

Vue.component("some-select", {
  methods: {
    doStuff: function(event) {
      this.$emit('change', event.target.value);
    }
  },
  template: `#vueTemplate-some-select`
});

var app = new Vue({
  el: "#my-app",
  data: {
    changeBus: new Vue()
  }
});
<script src="//unpkg.com/vue@latest/dist/vue.js"></script>
<div id='my-app'>
  <some-select @change="changeBus.$emit('change')"></some-select>
  <some-input :change-bus="changeBus"></some-input>
</div>
<script type="text/x-template" id="vueTemplate-some-select">
  <select @change="doStuff">
    <option value='1'>Value 1</option>
    <option value='2'>Value 2</option>
  </select>
</script>
<script type="text/x-template" id="vueTemplate-some-input">
  <input ref='text-some-input' type='text' value='Some Value' />
</script>

This approach ensures that each component remains encapsulated, with the parent component handling communication between the two child components in a decoupled manner.

Answer №2

To pass information from your select-component to the parent component, you must emit a custom event. Check out the VueJS Custom Events documentation for more information: VueJS Custom Events

Here's an example of how to set up the parent and select components:

<select-component @valueChanged="this.$refs.myInput.focus()"></select-component>
<input type="text" ref="myInput"/>

And here's how the select component emits the custom event:

<select v-model="mySelectValue" @change="$emit('valueChanged', mySelectValue)"></select>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

changing the contents of an array within the current state

My current task involves updating a list of names in the state before sending it as props to another component. // code snippet omitted for brevity this.state = { // other states here playerName: { player1Name: 'Default Player 1 Name ...

Access PHP variables in JavaScript

In my project, I have a file named english.php which holds various variable values stored in the $LANG array. For example: $LANG['value_1']="abc"; $LANG['value_2']="xyz"; In addition to numerous .php files that include require_once( ...

What is the best way to group/merge multiple objects that have the same name into a single object (Nesting)?

I have a dataset containing students' names and their marks in different subjects stored as an array of objects. My goal is to merge the data into a single object for each student with matching names, resulting in one record per student. Here is an ex ...

The JavaScript code is failing to retrieve any data from the API

import React, { Component } from 'react'; export class FetchData extends Component { static displayName = FetchData.name; constructor(props) { super(props); this.state = { users: [], loading: true }; } componentDidMount() { ...

jQuery Counter Effect encountering isNaN error when trying to display a number retrieved from a get API object

I am looking to display the numerical data retrieved from an API using JSON. I want to incorporate a counter effect that displays "isNaN" if necessary. The API URL returns an object with the total number saved in data.data. Can anyone assist me with achi ...

In JavaScript, escape is comparable to android decode

I used a JavaScript method to encode a string: var result = escape('Вася') The resultant string is: "%u0412%u0430%u0441%u044F" Now I need to decode this string in Java. How can I achieve this? The following attempt did not work: URLDecod ...

Reverting a concealed segment

Can anyone make sense of my unconventional explanation? I've set up a hidden section as shown below: <section class="intro"> <label> <input type="checkbox"> <span class="menu"> <span class="hamburger"></span&g ...

What is the method for pulling information from MySQL and presenting it on a website using Node.js?

Currently, my goal is to retrieve data from MySQL and showcase it on my HTML page. The code snippet in server.js looks like this: const path = require('path'); const express = require('express'); const bodyParser = require("body-pa ...

Deliver compressed data in gzip format from a Node.js server to the client using socket.io

I am currently facing an issue regarding determining whether the data being sent back to the client is compressed in gzip format or not. Upon examining my server's output from the command line, I notice the following: debug - websocket writing 3:::{" ...

Is Sending an Object to a Function in the Same Scope Inefficient?

Is there a noticeable delay when passing around an object within the same scope? Let's explore Option 1 and Option 2. In Option 1, we work directly with the object, while in Option 2 we follow better encapsulation practices. However, if we were to sti ...

Encountering a problem when utilizing webview in react native due to an error with the evaluation of

While utilizing webview for trading charts, I am encountering an issue where a warning is displayed and the URL fails to load. Below is the code snippet used for loading. It seems like the video URI works fine in full screen mode, but other URIs are not ...

No parameters have been found in the $router.push function

Imagine this scenario: this.$root.$router.push({ path: '/dashboard', params: { errors: 'error' }, query: { test: 'test' } }) Within my component, I am using the above code to redirect to another URL when an err ...

First time blur update unique to each user

By using ng-model-options="{ updateOn: 'blur' }", I can delay model updating until the user clicks out of an input field. This helps prevent constantly changing validation states while initially entering data. However, if a user revisits a field ...

Exploring the power of props in Vue3/Nuxt3: A guide to utilizing props directly in the

Could you assist me in resolving this issue : When accessing a value from the props within the root scope of <script setup>, reactivity is lost (vue/no-setup-props-destructure) The technologies I am using include : nuxt: "^3.6.5" typescri ...

I managed to pass an array of data to the client using EJS, but I encountered an issue trying to access the array on the client side after adding an index value

When I pass data received from an API to the client using EJS, I am struggling to access the JSON array on the client side. On the server side, I successfully send the returned data to the client like this: fetch(url) .then(res => res.json()) .the ...

JQuery, Draggable delete

I created a shopping cart with drag-and-drop functionality for nodes. http://jsfiddle.net/dkonline/Tw46Y/ Currently, once an item is dropped into the bucket (slot), it cannot be removed. I'm looking to add that feature where items can be removed from ...

Exploring the world of mocking and stubbing in protractor

I am interested in testing my angular application using protractor. The app includes an API Module that communicates with the server In these tests, I would like to mock this API Module. I am not looking to perform full integration tests, but rather tests ...

Oops! The API request was denied with error code 401 - Unauthorized in React

I have been working on incorporating an API into my front-end project using React/Typescript. The documentation for the API specifies that authorization requires a key named token with a corresponding value, which should be included in the header. To stor ...

HTML animation effect on subpage with a URL modification [LATEST UPDATE]

Can you smoothly load a new subpage in the background, update the URL, and fade it in while an animation is playing on the previous page? Check out this example (jsFiddle) to see a simple animation: $(document).ready(function() { 'use strict&apo ...

Angular version 1.6 with ES6, no errors in the application

Can you help me understand this? Note: I am using ui-router, and I suspect that is the issue. $stateProvider .state('login',{ url:'/', /*controller:'loginController',*/ controller: function(){aler ...