Reputation: 1951
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
Upvotes: 106
Views: 157204
Reputation: 1125
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.
Upvotes: 8
Reputation: 10852
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.
Upvotes: 129
Reputation: 27729
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>
Upvotes: 51
Reputation: 246
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>
Upvotes: 23