Search code examples
vue.jsselectinputfocus

VUE's focus() method return a console error? How to use it correctly?


I'm trying to focus on several elements of my form but the first one, despite being applied, returns an error by console. This is my template:

  <div class="container">
    <div class="col-xs-12">
      <div class="row">
        <h1 class="animal-title">Your selection is : </h1>
      </div>

      <div class="wrapper">
        <form class="first-form" @submit.prevent="onSubmit">
          <div class="image-wrapper">
            <div class="sel-image">
              <div v-on:click="imageSelected = true" v-for="item in items" v-bind:key="item.id">
                <label>
                  <input
                    type="radio"
                    name="selectedItem"
                    ref="item"
                    :value="item.id"
                    v-model="itemFormInfo.selectedItem"
                    @change="onChangeItem($event)"
                  />
                  <img v-if="item.id === 1" src="../../assets/1.png" />
                  <img v-if="item.id === 2" src="../../assets/2.png" />
                  <img v-if="item.id === 3" src="../../assets/3.png" />
                </label>
                <p class="cie-animal-subtitle">{{item.name}}</p>
              </div>
            </div>
          </div>

          <div class="form-select">
            <div v-show="filteredStock && (imageSelected || itemFormInfo.selectedItem) > 0">
              <h1 v-if="this.itemName === 'Phone' || this.itemName === 'Tablet'" for="selectedItem" ref="itemVisible">
                Select the brand of your <span>{{this.itemName}}</span> :
              </h1>
              <h1 v-if="this.itemName === 'PC'" for="selectedBreed" ref="itemVisible">
                Select the type of your <span>{{this.itemName}}</span> :
              </h1>
              <select
                ref="brand"
                class="form-control"
                id="selectedBrand"
                v-model="itemFormInfo.selectedBrand"
                @change="onChangeBrand($event)">
                <option v-for="brand in filteredBrand" v-bind:key="brand.name">{{ brand.name }}</option>
              </select>
              <div v-show="this.isBrandSelected">
                <h1>What are you going to use your 
                  <span>{{itemName}}</span> for ?
                </h1>
                <input
                  type="text"
                  id="componentName"
                  ref="componentName"
                  class="form-control fields"
                  style="text-transform: capitalize"
                  v-model="itemFormInfo.component"
                  @keypress="formChange($event)"
                />
                <div class="loader-spinner" v-if="loading">
                  <app-loader/>
                </div>
              </div>
            </div>
          </div>
          <div class="service-options" v-show="isComponentCompleted">
            <div class="from-group">
              <h1>
                Here are the options for your <span>{{this.itemFormInfo.component}}</span> :
              </h1>
              <div class="services">
                <div class="column-service" v-for="option in options" v-bind:key="option.name">
                  <div class="service-name">{{option.name}}</div>
                  <div class="service-price">{{option.price.toString().replace(".", ",")}} </div>
                </div>
              </div>


and here my first method

    onChangeItem(event) {
      let item = event.target._value;
      this.itemName = this.getItemName(item);      
      if (this.isItemSelected = true) {
        this.isItemSelected = false;
        this.isComponentCompleted = false;
        this.isLoaderFinished = false;
        this.itemFormInfo.name = ""
      }
    this.$refs.item.focus();
    },

in this function that I control my first input, the focus is working but it returns me by console the following error:

"this.$refs.item.focus is not a function at VueComponent.onChangeItem"

I have seen some references to similar cases where they involved the reference in a setTimeout or used the this.$nextTick(() => method but it didn't work in my case.

What am I doing wrong? How can I focus on the next select with ref brand, once I have chosen the value of the first input?

Thank you all for your time and help in advance


Solution

  • How can I focus on the next select with ref brand, once I have chosen the value of the first input?

    You want to put focus on brand but your onChangeItem handler is calling this.$refs.item.focus() (trying to focus item). Seems strange to me...

    Reason for the error is you are using ref inside v-for.
    Docs: When used on elements/components with v-for, the registered reference will be an Array containing DOM nodes or component instances

    So the correct way for accessing item ref will be this.$refs.item[index].focus().

    Just be aware that right now v-for refs do not guarantee the same order as your source Array - you can find some workarounds in the issue discussion...