andriy_sof
andriy_sof

Reputation: 2743

How to access custom attributes from event object in React?

React is able to render custom attributes as described at http://facebook.github.io/react/docs/jsx-gotchas.html:

If you want to use a custom attribute, you should prefix it with data-.

<div data-custom-attribute="foo" />

And that's great news except I can't find a way to access it from the event object e.g.:

render: function() {
...
<a data-tag={i} style={showStyle} onClick={this.removeTag}></a>
...
removeTag: function(event) {
    this.setState({inputVal: event.target????}); 
},

The element and data- property render in html fine. Standard properties like style can be accessed as event.target.style fine. Instead of event.target I tried:

 event.target.props.data.tag
 event.target.props.data["tag"]
 event.target.props["data-tag"]  
 event.target.data.tag
 event.target.data["tag"]
 event.target["data-tag"]

none of these worked.

Upvotes: 271

Views: 358374

Answers (17)

Yilmaz
Yilmaz

Reputation: 49293

If you have multiple icons with different data-label (age,name,email):

       <button
          data-label="name" 
          onMouseOver={handleValue}
          className="icon"
        >
          <FaUser />
        </button>

when the mouse is over an icon, you change the title by accessing data-label

const handleValue = (e) => {
    // making sure mouse is over an icon
    if (e.target.classList.contains("icon")) {
      const newValue = e.target.dataset.label;
      setTitle(newValue);
      setValue(person[newValue]);
    }
  };

Upvotes: 1

Milan
Milan

Reputation: 25

This worked for me... My attribute is named "attr" in the example.

e.target.selectedOptions[0].attributes.attr.value

Upvotes: 1

Amitesh Bharti
Amitesh Bharti

Reputation: 15713

I think it's recommended to bind all methods where you need to use this.setState method which is defined in the React.Component class, inside the constructor, in your case you constructor should be like

    constructor() {
        super()
        //This binding removeTag is necessary to make `this` work in the callback
        this.removeTag = this.removeTag.bind(this)
    }
    removeTag(event){
        console.log(event.target)
        //use Object destructuring to fetch all element values''
        const {style, dataset} = event.target
        console.log(style)
        console.log(dataset.tag)
    }
   render() {
   ...
      <a data-tag={i} style={showStyle} onClick={this.removeTag.bind(null, i)}></a>
   ...},

For more reference on Object destructuring https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#Object_destructuring

Upvotes: 0

Vikash Kumar
Vikash Kumar

Reputation: 419

You can simply use event.target.dataset object . This will give you the object with all data attributes.

Upvotes: 4

Sophie Alpert
Sophie Alpert

Reputation: 143134

event.target gives you the native DOM node, then you need to use the regular DOM APIs to access attributes. Here are docs on how to do that:Using data attributes.

You can do either event.target.dataset.tag or event.target.getAttribute('data-tag'); either one works.

Upvotes: 390

Emeka Augustine
Emeka Augustine

Reputation: 931

This single line of code solved the problem for me:

event.currentTarget.getAttribute('data-tag')

Upvotes: 9

Rameez Iqbal
Rameez Iqbal

Reputation: 507

You can access data attributes something like this

event.target.dataset.tag

Upvotes: 7

msangel
msangel

Reputation: 10362

Try instead of assigning dom properties (which is slow) just pass your value as a parameter to function that actually create your handler:

render: function() {
...
<a style={showStyle} onClick={this.removeTag(i)}></a>
...
removeTag = (customAttribute) => (event) => {
    this.setState({inputVal: customAttribute});
}

Upvotes: 3

Manindra Gautam
Manindra Gautam

Reputation: 387

<div className='btn' onClick={(e) =>
     console.log(e.currentTarget.attributes['tag'].value)}
     tag='bold'>
    <i className='fa fa-bold' />
</div>

so e.currentTarget.attributes['tag'].value works for me

Upvotes: 11

tytk
tytk

Reputation: 2332

As of React v16.1.1 (2017), here is the official solution: https://reactjs.org/docs/handling-events.html#passing-arguments-to-event-handlers

TLDR: OP should do:

render: function() {
...
<a style={showStyle} onClick={(e) => this.removeTag(i, e)}></a>
...
removeTag: function(i, event) {
    this.setState({inputVal: i}); 
}

Upvotes: 9

Eduardo
Eduardo

Reputation: 41

If anyone is trying to use event.target in React and finding a null value, it is because a SyntheticEvent has replaced the event.target. The SyntheticEvent now holds 'currentTarget', such as in event.currentTarget.getAttribute('data-username').

https://facebook.github.io/react/docs/events.html

It looks like React does this so that it works across more browsers. You can access the old properties through a nativeEvent attribute.

Upvotes: 4

Mentori
Mentori

Reputation: 426

// Method inside the component
userClick(event){
 let tag = event.currentTarget.dataset.tag;
 console.log(tag); // should return Tagvalue
}
// when render element
<a data-tag="TagValue" onClick={this.userClick}>Click me</a>

Upvotes: 25

miguel savignano
miguel savignano

Reputation: 1159

In React you don't need the html data, use a function return a other function; like this it's very simple send custom params and you can acces the custom data and the event.

render: function() {
...
<a style={showStyle} onClick={this.removeTag(i)}></a>
...
removeTag: (i) => (event) => {
    this.setState({inputVal: i}); 
},

Upvotes: 0

Jared Forsyth
Jared Forsyth

Reputation: 13162

To help you get the desired outcome in perhaps a different way than you asked:

render: function() {
    ...
    <a data-tag={i} style={showStyle} onClick={this.removeTag.bind(null, i)}></a>
    ...
},
removeTag: function(i) {
    // do whatever
},

Notice the bind(). Because this is all javascript, you can do handy things like that. We no longer need to attach data to DOM nodes in order to keep track of them.

IMO this is much cleaner than relying on DOM events.

Update April 2017: These days I would write onClick={() => this.removeTag(i)} instead of .bind

Upvotes: 183

roctimo
roctimo

Reputation: 894

Here's the best way I found:

var attribute = event.target.attributes.getNamedItem('data-tag').value;

Those attributes are stored in a "NamedNodeMap", which you can access easily with the getNamedItem method.

Upvotes: 57

Dimitrios Ververidis
Dimitrios Ververidis

Reputation: 1215

I do not know about React, but in the general case you can pass custom attributes like this:

1) define inside an html-tag a new attribute with data- prefix

data-mydatafield = "asdasdasdaad"

2) get from javascript with

e.target.attributes.getNamedItem("data-mydatafield").value 

Upvotes: 3

Tudor Campean
Tudor Campean

Reputation: 351

Or you can use a closure :

render: function() {
...
<a data-tag={i} style={showStyle} onClick={this.removeTag(i)}></a>
...
},
removeTag: function (i) {
    return function (e) {
    // and you get both `i` and the event `e`
    }.bind(this) //important to bind function 
}

Upvotes: 25

Related Questions