107

I have some dynamic <input> elements in my dom rendered from for loop in vue. I need to add ref property to each of them by appending an Id to each ref like element1,element2,..etc. How to do this in vue?

<div v-for="(result, index) in data" :key="index">
    <input type="text" type="file" ref="element" />
</div>

How to add ref if result.id exists

1
  • 1
    I'm doing something similar with my app and it seems to slow things down a lot when dynamically adding refs to my component. At least I think that's what is happening. Curious if you experienced something similar. Commented May 22, 2018 at 22:43

4 Answers 4

129

Simply use v-bind like :ref="'element' + result.id" or ref="`element${result.id}`".

Check fiddle here.

new Vue({
  el: '#app',
  data: {
    data: [{id: 1}, {id: 2}, {id: 3}],
  },
  mounted() {
    console.log(this.$refs);
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>

<div id="app">
<div v-for="(result, index) in data" :key="index">
    <input type="text" type="file" :ref="'element' + result.id" />
</div>
</div>

Edited: Thanks to Vamsi's edit, I replaced index with result.id
Edited 8/28: Thanks to grokpot, I added a sample powered by Template literals.

Sign up to request clarification or add additional context in comments.

4 Comments

@VamsiKrishna Thanks a lot for your edit. I changed a few code again to make it work.
This results in an array. See github.com/vuejs/vue/issues/2044
you may also use a template literal: ref="`element${result.id}`")
@grokpot Yes, but don't forget the : before ref, otherwise the ref will be literally `element${result.id}`
51

Using v-bind:ref or just :ref.

Follow below a simple example including how to access a dynamic ref

<template>
    <div>
        <div class="inputs" v-for="input in inputs" :key="input.id">
            <input type="text" v-model="input.name" :ref="'name' + input.id">
            <button @click="displayRef('name' + input.id)">
                 Click to see the input ref
            </button>
            <hr>
            <button @click="displayAllRefs">Click to see all refs</button>
        </div>
    </div>
</template>

And the script:

<script>
    export default {
        data() {
            return {
                inputs: [
                    { id: Date.now(), name: '', lastName: '' }
                ]
            }
        },
        methods: {
            displayRef(ref) {
                console.log(this.$refs[ref]) // <= accessing the dynamic ref
                console.log('The value of input is:',this.$refs[ref][0].value) //<= outpouting value of input
            },
            displayAllRefs() {
                console.log(this.$refs)
            }
        }
    }
</script>

2 Comments

Why does one have to access the ref with a [0]?
@TobiasFeil When using refs within v-for, this.$refs[key] returns an array of elements rather than a single element, even if only one exists. vuejs.org/v2/guide/…
23

You have dynamic refs and have multiple elements. To target any single node just pass the index within method params

     new Vue({
      el: '#app',
      data: {
        data: [{id: 1}, {id: 2}, {id: 3}],
      },
       methods: {
      addNewClass(index) {
      
      this.$refs.element[index].classList.add('custom-class')
    }
  },
    
    })
<script src="https://npmcdn.com/vue/dist/vue.js"></script>

     
<div id="app">
  <div v-for="(result, index) in data" :key="index">
   <div ref='element' @click='addNewClass(index)' class='custom-container'>
        
   </div>
</div>

1 Comment

This is brilliant, this is a feature of Vue that I didn't know about. It automagically generates an array of elements. Thanks for this!
11

Update for Vue 3.2.47+: if specifically you need to access elements of a v-for, you can attach a ref to an array directly: (docs). Example code

<script setup>
// ...
const itemRefs = ref([]);
</script>

<template>
  <Comp v-for="item in list" ref="itemRefs">
    {{ item }}
    {{ itemRefs[2] }}
  </Comp>
<template>

If your v-for is a list of custom components, be sure to expose any fields or functions you need with defineExpose.

If furthermore you require that the list of refs maintain the same order, I found this answer to be very helpful.

1 Comment

Perhaps additional code is needed to refresh the refs array if the list changes?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.