Reputation: 31
I have a list of items using material-ui. I would like to call _handleTouchTap() when the item is clicked and pass the key of the ListItem to the handler.
Adding
onTouchTap={this._handleTouchTap}
to is not working as 'this' seems the be the wrong scope
var React = require('react');
var Mui = require('material-ui');
var ThemeManager = new Mui.Styles.ThemeManager();
ThemeManager.setTheme(ThemeManager.types.LIGHT);
var injectTapEventPlugin = require('react-tap-event-plugin');
injectTapEventPlugin();
var List = Mui.List
var ListItem = Mui.ListItem
var Main = React.createClass({
childContextTypes: {
muiTheme: React.PropTypes.object
},
getChildContext: function () {
return {
muiTheme: ThemeManager.getCurrentTheme()
}
},
render: function() {
var items = [
{id: 1, title: 'Item 1'},
{id: 2, title: 'Item 2'},
{id: 3, title: 'Item 3'}
]
return (
<List>
{items.map(function(item){
return <ListItem key={item.id} primaryText={item.title} />
})}
</List>
)
},
_handleTouchTap: function() {
// the key of the item should be passed though here
}
});
React.render(<Main />, document.body);
Upvotes: 3
Views: 14642
Reputation: 180
If you want to use the newer ES6 class syntax and arrow function, this could be the answer. You need to explicitly bind the this
keyword if you are using class syntax to correctly specify the this
context. onTouchTap
expects a method, so I'm returning a function using ES6 arrow function.
import { Component, React } from 'react';
import { List, ListItem } from 'material-ui/List';
class Main extends Component {
constructor() {
super(...arguments);
this._handleTouchTap = this._handleTouchTap.bind(this);
}
_handleTouchTap(id) {
return () => console.log(id) // Logs item id
}
render () {
var items = [
{id: 1, title: 'Item 1'},
{id: 2, title: 'Item 2'},
{id: 3, title: 'Item 3'}
];
return (
<List>
{items.map(function(item){
return (
<ListItem
key={item.id}
primaryText={item.title}
onTouchTap={this._handleTouchTap(item.id)}
/>
)
})}
</List>
);
}
}
Upvotes: 1
Reputation: 1482
If event.target.id
isn't working due to concerns that Tim Welch pointed out above, you can simply pass the item ID as a parameter to your handler function
render: function() {
var items = [
{id: 1, title: 'Item 1'},
{id: 2, title: 'Item 2'},
{id: 3, title: 'Item 3'}
]
return (
<List>
{items.map(function(item){
return <ListItem key={item.id}
primaryText={item.title}
onTouchTap={this._handleTouchTap.bind(this, item.id)}/>
})}
</List>
)
},
_handleTouchTap: function(id) {
console.log(id) // Logs item id
}
});
Instead of using onTouchTap={this._handleTouchTap.bind(this, item.id)}
, if you're using es6 you can instead use an es6 fat arrow function which will automatically bind this
for you. It can be done like this:
onTouchTap={() => this._handleTouchTap(item.id)}
Upvotes: 7
Reputation: 41
Sharing what I learned. Take a look at the MakeSelectable higher-order component that Material-UI offers for creating a selectable List that gives you the index of the currently selected item onChange. This might be new since the question was asked. Note the value attribute on the ListItem's below and the onChange event on the SelectableList.
import {List, ListItem, MakeSelectable} from 'material-ui/List'
SelectableList = MakeSelectable(List)
const siteItems = Object.keys(sites || {}).map((index) => {
const site = sites[index]
return (<ListItem
key={index + 1}
value={site.id}
leftAvatar={<Avatar icon={<PinDrop />} />}
primaryText={site.name}
secondaryText={site.description}
style={styles.list}
/>)
})
CurList = (
<div style={styles.listcontainer}>
<SelectableList onChange={this.siteSelected}>
{siteItems}
</SelectableList>
</div>
)
The problem I found with pattern of setting the id of the listitem and trying to access it via event.target.id is that event.target will vary if you have sub-elements in your List item like icons, labels, etc. which most of the List examples have.
Upvotes: 1
Reputation: 1
you have to set the listitem onTouchTap prop and set event to handleTouchTap parameter
<ListItem onTouchTap={this._handleTouchTap} />
_handleTouchTap: function(event){
var clickedID = event.target.id
}
Upvotes: 0