2

I have a React application in which I have a select tag with children option tags. For each option tag, I am passing some extra data that I want associated with each option and eventually retrieved to be passed into other helper functions.

const MyDropdown = () => {
    const _onChange = e => {
        // Here, I want to get the data attribute data-otherData and pass it into a function call.
        console.log(e.target.dataset.otherData) // returns undefined
        console.log(e.target.getAttribute("data-otherData") // returns null
    }

    return (
        <select onChange={_onChange}>
            <option value="USA" data-otherData="selectLocation_US">I live in USA</option>
            <option value="CA" data-otherData="selectLocation_CA">I live in Canada</option>
            <option value="UK" data-otherData="selectLocation_UK">I live in UK</option>
            <option value="AU" data-otherData="selectLocation_AU">I live in Australia</option>
        </select>
    )
}

By doing various searches on the Web, I determined that I should either do event.target.dataset.otherData or event.target.getAttribute("data-otherData") in order to access my data attributes. However, none of those work.

Does anyone know what my issue is?

EDIT: I've created a fiddle to show what is happening: https://jsfiddle.net/mp8ns90o/

It was pointed out to me that the data attributes should be in kebab case and accesses to dataset should be in camelCase.

So, I've tried: I live in USA

and tried to retrieve it by using e.target.dataset.otherData and e.target.getAttribute('data-other-data') and it still doesn't work.

2
  • Are you sure the dropdown exists at the time that you are attempting to gain access to it? Commented May 5, 2021 at 19:40
  • I believe so. I'm manually clicking the option in the dropdown in order to trigger the onChange event and expecting to retrieve the unique data but not getting it. Commented May 5, 2021 at 19:42

2 Answers 2

1

When you use camelCase in JavaScript to look up the value in the dataset, it will look actually look for those words in kebabcase. I.E. data-other-data.

To get a data attribute through the dataset object, get the property by the part of the attribute name after data- (note that dashes are converted to camelCase).

The easiest option would be to fix your naming convention in the markup to conform.

https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

const article = document.querySelector('#electric-cars');

console.log(article.dataset.columns) // "3"
console.log(article.dataset.indexNumber) // "12314"
console.log(article.dataset.parent) // "cars
<article
  id="electric-cars"
  data-columns="3"
  data-index-number="12314"
  data-parent="cars">
...
</article>

This behavior is consistent throughout the browser API. For example If you want to set an elements border-width, you use the camelCase form element.style.borderWidth

Furthermore, you need to grab the option manually. This is because your event target is always the select and not the option itself.

const onChangeHandler = ({target}) => {
    let lbl = target
      .querySelector(`option[value="${target.value}"]`)
      .dataset
      .eventLabel
    console.log(lbl);     
}

fixed fiddle: https://jsfiddle.net/5ngx1p0t/

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

3 Comments

That's a good point so I just tried that and it doesn't work either. I've created a fiddle to show what is happening and edited my original post. jsfiddle.net/mp8ns90o
I know whats wrong though. See you trigger the event always on the select and the options set its value but they dont set its dataset. So you always hav as event target the select and not the option. You need to grab the option manually in the callback.
D'oh! That was it. Thanks for helping me out on that.
1

How about...

const options = {
    USA: {
        location: 'selectLocation_US',
        label: 'I live in USA',
    },
    CA: {
        location: 'selectLocation_CA',
        label: 'I live in Canada',
    },
    UK: {
        location: 'selectLocation_UK',
        label: 'I live in UK',
    },
    AU: {
        location: 'selectLocation_AU',
        label: 'I live in Australia',
    }
}

const _onChange = e => {
    console.log(options[e.target.value].location)
}

const MyDropdown = () => {
    return (
        <select onChange={_onChange}>
            {
                Object.entries(options).map(([k, v]) => {
                    return (
                        <option value={k}>{v.label}</option>
                    )
                })
            }
        </select>
    )
}

return MyDropdown()

Comments

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.