Ondrej Vencovsky
Ondrej Vencovsky

Reputation: 3508

Get reference to element in method in Vue.js

How can I get reference to the element that fired the method in Vue.js? I have HTML like this:

 <input type="text" v-model="dataField" v-bind:class="dataFieldClass" />

And in my Vue.js viewmodel I have a method:

dataFieldClass: function () {
    // Here I need the element and get its ID
    // Pseudo code
    var elementId = $element.id;
}

I know that it's possible to get the element from event (v-on:click), but this is not an event, it's a simple method returning CSS class for the element according to few conditions of the viewmodel. It should be computable as well, but the problem is the same.

Upvotes: 39

Views: 81359

Answers (7)

FitzFish
FitzFish

Reputation: 8629

What about using the ref pattern. Put ref="someName" in your DOM element, and access it in your method with this.$refs["someName"] (you can pass 'someName' as parameter to your method).

Note that's not a very good pattern except if for some reason you really need the DOM element. Otherwise just pass a relevant parameter to your method.

It's not a good method mainly because it has a major drawback: there is no $refs the first time the vue is rendered (because the element is not present yet). So you should force the vue to render twice.

If you have multiple elements inside a v-for loop, then this.$refs["someName"] becomes an array. You can get it to work with some adaptation, here is an example:

new Vue({
  el: '#app',
  data() {
    return {
      fields: [{
          name: 'field1',
          value: 'value1'
        },
        {
          name: 'field2',
          value: 'value2'
        }
      ]
    };
  },
  methods: {
    dataFieldClass(index) {
      if (!this.$refs.fields) {
        // First render, the element is not there yet
        return '';
      } else {
        // Here is the element
        console.log(this.$refs.fields[index]);
      }
    }
  },
  mounted() {
    // Force the instance to render a second time
    this.$forceUpdate();
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script>

<div id="app">
  <label v-for="(field, index) in fields">
    {{ field.name }}:
    <input ref="fields" :value="field.value" v-bind:class="dataFieldClass(index)">
  </label>
</div>

Upvotes: 7

robinalaerts
robinalaerts

Reputation: 559

You can get the reference to your element in three ways

1. with Method Event Handlers (doc)

template:

<input type="text" v-model="dataField" v-bind:class="dataFieldClass" />

script:

dataFieldClass: function (e) {
    const element = e.target;
}

2. with Inline Handlers (doc)

template:

 <input type="text" v-model="dataField" v-bind:class="dataFieldClass($event, otherArgument)" />

script:

dataFieldClass: function (e, otherArgument) {
    const element = e.target;
}

3. with Refs (doc)

template:

 <input type="text" v-model="dataField" v-bind:class="dataFieldClass" ref="el"/>

script:

dataFieldClass: function () {
    const element = this.$refs.el;
}

Upvotes: 38

Daniel Diekmeier
Daniel Diekmeier

Reputation: 3434

Maybe you could use ref?

<input type="text" v-model="dataField" v-bind:class="dataFieldClass" ref="el" />

And use it like this:

dataFieldClass: function () {
    var elementId = this.$refs.el;
}

See documentation here: https://v2.vuejs.org/v2/api/#ref

Upvotes: 13

tomshy
tomshy

Reputation: 45

You can use refs as mentioned in other answers here.

Remember, refs cannot apply to computed objects. So be careful when using refs

Upvotes: 0

atazmin
atazmin

Reputation: 5707

This seem to work for me, using ref (if element is nested another element)

<div ref="element">

vm.$refs.element

or $el if targeted element is the outermost

<template><div class="targeted-element">

this.$el

Upvotes: 0

roshnet
roshnet

Reputation: 2073

A straightforward solution is to pass a reference to the element in the method to be called.

Here's what worked for me (a pretty basic example to help understand):

new Vue({
  el: '#app',
  data: {
    msg: '',
  },
  methods: {
    // in order to access the HTML element,
    // add an argument (namely 'event') in the method definition,
    // and access the element's current value by `event.target.value`
    updateValue: function(event) {
      this.msg = event.target.value;
    }
  }
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>

<div id="app">
  <input :value="msg" @input="updateValue" autofocus>
  <br/>
  <h2>
    >>> {{ msg }}
  </h2>
</div>

Upvotes: 0

Heesoo Lee
Heesoo Lee

Reputation: 49

You can get the reference from DOM event object. "event.currentTarget" is the property that references the element where the event listener(vuejs method) assigned.

This is standard DOM specification, but you can also use this property in Vuejs.

dataFieldClass: function (event) {
    var elementId = event.currentTarget.id;
}

Upvotes: 3

Related Questions