Unleash the power of Vue2 with composition API for creating dynamic template refs

Currently, I am utilizing Quasar (quasar.dev) in conjunction with Vue2 + Composition API and attempting to access DOM elements that have dynamically generated 'v-bind:ref' properties. This approach is based on the information provided in this section of the Vue3 documentation:

https://v3.vuejs.org/guide/composition-api-template-refs.html#usage-inside-v-for

To better illustrate the issue, I have created a simplified representation on codesandbox: https://codesandbox.io/s/suspicious-pine-90qgd?file=/src/components/MyOuterComponent.ts

The template for my component (MyOuterComponent.vue):

<template>
  <div>
    <my-component
      v-for="(item, i) in list"
      v-bind:ref="
        (el) => {
          if (el) divs[i] = el
        }
      "
      v-bind:key="i"
    >
      {{ item }}
    </my-component>
  </div>
</template>

<script src='./MyOuterComponent.ts' />

Here is the script for the component:

import MyComponent from './MyComponent.vue'
import TMyComponent from './MyComponent'
import {
  defineComponent,
  onMounted,
  ref,
  reactive,
  onBeforeUpdate
} from '@vue/composition-api'
export default defineComponent({
  name: 'MyOuterComponent',
  components: { MyComponent },
  props: {},
  setup(props, context) {
    const list = reactive([1, 2, 3, 4, 5])
    const divs = ref<InstanceType<typeof TMyComponent>[]>([])

    // Ensure the refs are reset before each update
    onBeforeUpdate(() => {
      divs.value = []
    })

    onMounted(() => {
      context.root.$nextTick(() => {
        console.log('THE COMPONENTs', divs, context.root.$refs)
        divs.value.forEach((div) => {
          console.log('My Div Ref: ', div)
        })
      })
    })
    return {
      list,
      divs
    }
  }
})

According to the documentation, I anticipate that divs will contain the template refs for my dynamically generated components, thanks to this line in my template:

v-bind:ref="(el) => { if (el) divs[i] = el }"

Despite logging after nextTick, divs remains empty. I was hoping to see 5 items referencing DOM elements within it.

If I modify the template to the following:

<template>
  <div>
    <my-component
      v-for="(item, i) in list"
      v-bind:ref="item"
      v-bind:key="i"
    >
      {{ item }}
    </my-component>
  </div>
</template>

<script src='./MyOuterComponent.ts' />

In this case, I can locate the refs in context.refs, although I have been informed that this feature will be eliminated in Vue3. Can someone kindly point out where I may have made an error? Thank you.

Answer №2

To begin, the first step is to import ref:

import { ref } from "@vue/composition-api"

An easy method involves adding a ref to a list. By using the list index, you can access the necessary ref.

<template>
  <div>
    <my-component
      ref="mycomponentRef"
      v-for="(item, index) in list"
      v-bind:key="index"
    >
      {{ item }}
    </my-component>
  </div>
</template>

<script>
export defineComponent({
  setup() {
    // an array containing refs, e.g., [ref0, ref1, ...]
    const mycomponentRef = ref()

    return { mycomponentRef }
  }
})
</script>

Answer №3

Even though it is currently not officially supported, there is a way to access the old $refs as a temporary solution. This feature is not available in Vue3, but you can use this workaround until it is implemented.

  <div v-for='i of 10' :key='i' ref='myRefs' />
setup(props, {refs}){
  // Temporary fix until Vue2 Composition API includes support for dynamic template refs.
  onMounted(()=>{
     myRefs = refs.myRefs // array of 10 refs
  })
}

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

Identifying the absence of a character at the end of the last line in Node.js to detect

Currently, I am processing data line by line from a buffer. Within the buffer, the data is structured as follows: name,email,phn test1,<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="47332234337607223f262a372b226924282a">[em ...

IE11 and how it handles Typescript and promises

Currently, I am utilizing Typescript version 2.4.2 along with Webpack for compilation purposes. Despite successful compilation, when running my code on IE11, an error 'Promise' is undefined arises. Below is a glimpse of my tsconfig: { "comp ...

Tips for accessing store data within the mounted lifecycle hook in a Vuex component

In my project, I have the main root component called App.vue and another component named FileUploaderParent.vue. I am using a dispatch promise to store data in the Vuex store. The dispatch call is made under the mounted lifecycle hook. However, when I try ...

What steps should one take to address issues related to Datatables in Laravel and Vue?

I encountered an issue while trying to fetch data into a datatable in Laravel. I am receiving an error message stating "Uncaught ReferenceError: $ is not defined" on the console of the page. Is there a solution to resolve this problem? index.blade.php ...

What could be the reason for TypeScript throwing an error that 'product' does not exist in type '{...}' even though 'product' is present?

Structure of Prisma Models: model Product { id String @id @default(auto()) @map("_id") @db.ObjectId name String description String price Float image String createdAt DateTime @default(now()) updatedAt Da ...

Vue router navigation guards

Issue arises when the name becomes an undefined value and I am unsure of the reason behind it. click here for image description router.beforeEach((to, from, next) => { console.dir(to); }); ...

Injector in Angular is a tool used for dependency injection

I have multiple components; I am using Injector in the constructor for encapsulation import { Component, Injector, OnInit } from '@angular/core'; @Component({ selector: 'app-base', templateUrl: './base.component.html', ...

When navigating using the next and back buttons, the active state in Angular is automatically removed

Looking for some assistance with my quiz app setup. Each question has True/False statements with corresponding buttons to select T or F. However, when I click the next/back button, the active class is not being removed from the previous selection. As a beg ...

Displaying a single photo on mobile, while simultaneously showing four photos on the web using Nuxt.js

When viewing the web browser from a mobile device, only one image should be displayed instead of all four images fetched from an API. What are some possible ways to achieve this? The data retrieved includes all the images at once. <template> <d ...

Easy Steps to Retrieve a Formatting String in Vue.js

Hi, I am currently working with this script: <div class="description text-left" v-for="item in siteObject.line_info"> <small>{{siteObject.line_info}}</small> </div> I am currently seeing this view: [ { "lineid": "BN00003054538", " ...

Creating a unique Web Component that spans the full height of the page

I created a Web Component with Vue.js and vue-custom-element. I now want my my-chat and my-whiteboard Web Components to have a height of 100%. Here's how I'm using the component: // App.vue <template> <splitpanes class="default-theme" ...

Guide to Integrating Pendo with Angular 8 and Above

I'm having some trouble setting up Pendo in my Angular 8 application. The documentation provided by Pendo doesn't seem to align with the actual scripts given in my control panel. Additionally, the YouTube tutorials are quite outdated, appearing t ...

Anticipated the object to be a type of ScalarObservable, yet it turned out to be an

When working on my Angular project, I utilized Observables in a specific manner: getItem(id): Observable<Object> { return this.myApi.myMethod(...); // returns an Observable } Later, during unit testing, I successfully tested it like so: it(&apos ...

Using ngFor directive to iterate through nested objects in Angular

Receiving data from the server: { "12312412": { "id": "12312412", "something": { "54332": { "id": "54332", "nextNode": { "65474&q ...

Dynamically Generating URL for Dropzone Image Upload

I recently incorporated a dropzone component in my Vue project. Now, I am trying to dynamically modify the URL for image uploads. Please refer to the screenshot attached for details: Screenshot ...

Is there a way to modify the antd TimePicker to display hours from 00 to 99 instead of the usual 00 to 23 range?

import React, { useState } from "react"; import "./index.css"; import { TimePicker } from "antd"; import type { Dayjs } from "dayjs"; const format = "HH:mm"; const Clock: React.FC = () =& ...

I encountered an error while attempting to integrate Vue.js into Laravel, stating: "Error: Cannot locate module 'webpack/lib/rules/DescriptionDataMatcherRulePlugin'"

https://i.sstatic.net/MivKf.png I've been implementing Vue.js into my Laravel application using the following code snippets. composer require laravel/ui php artisan ui vue npm install npm run watch-poll npm mix "--watch" "--watch-poll& ...

"CanDeactivate Implementation Failure: Why isn't the Generic Function Being Called

I am currently working on implementing a guard to prevent users from navigating to the login page once they have authenticated themselves. This guard should apply to all page components in my app except for the login page. Below is the code snippet I am u ...

How can we use Angular Table to automatically shift focus to the next row after we input a value in the last cell of the current row and press the Enter key

When the last cell of the first row is completed, the focus should move to the next row if there are no more cells in the current row. <!-- HTML file--> <tbody> <tr *ngFor="let row of rows;let i=index;" [c ...

Icons on Speed-Dial are not aligning to the center

I've been working on creating a Speed Dial feature for a web application, but I can't seem to get the icons to align properly in the Speed Dial menu. Despite following the instructions provided in https://vuetifyjs.com/en/components/floating-act ...