Storing extra data within your HTML elements using data-* attributes

I came across a simple problem, I have an array of objects in React with a name (something to display to the user) and an expression tree (which makes up a query associated with the name).

What I wanted to do is that when a name is selected in a material-ui Select component, that it then passes the name and the expression data to a handler.

Ofcourse there are several ways to achieve this but this is a really simply solution. We create an array of MenuItem‘s for the Select and we store the expression tree along with the MenuItem

If you take a look at Using data attributes you’ll see that HTML5 has a way of adding attributes to an element using the data-* syntax.

The name of the attribute to be added simply starts with data-, for example data-expression and now when the Select onChange event is handled, we can get at, not only the value selected but also the data attribute value.

Here’s an example of us setting up a MenuItem

return [{name: "None", expression: undefined}]
  .concat(publicQueries).map(e => {
    return <MenuItem key={e.name} 
      value={e.name} 
      data-expression={e.expression}>{e.name}</MenuItem>
});

Notice that we simply declare the data-expression and assign some data to it. Nothing special here.

Now within the onChange handler of the Select component we might have a handler like this

handleOnChange(e: any, child?: any) {
   const selecteNamed = e.target.value;
   const selectedExpression = child.props['data-expression'];
   // do something useful with these
}