Material UI List onClick fires click event on nested list - reactjs

I have a material ui list in my one of the component. When I click any item of this list, I go to another listView. I am using router to go to another listView. And using onClick method. Whenever I click any list item of first list I print "firstList clicked". and whenever I click any item if second list, it print "secondList clicked".
Here is my Problem:
When I click the ListItem of first list, the console.log("secondList clicked") also gets printed with "firstList Clicked" automatically. I have four list items in second list, so my console print output looks like this
firstList Clicked
secondList Clicked
secondList Clicked
secondList Clicked
secondList Clicked
Why is this happening?
Here is my code.
SecondList code
class TagListItemDetails extends Component {
handleClick() {
console.log("secondList clicked")
}
handleButtonClick() {
browserHistory.push("TagList")
}
render() {
return (
<MuiThemeProvider>
<div>
<List id="parent-list-tags">
<ListItem primaryText="Kitchen" onTouchTap={this.handleClick()}/>
<ListItem primaryText="Beach" onClick={this.handleClick()}/>
<ListItem primaryText="Marriage" onClick={this.handleClick()}/>
<ListItem primaryText="Garden" onClick={this.handleClick()}/>
</List>
<div className="backButton">
<RaisedButton backgroundColor="#293C8E" label="Back" onClick={this.handleButtonClick} labelColor="white">
</RaisedButton>
</div>
</div>
</MuiThemeProvider>
);
}
}
const mapStateToProps =(state) =>{
return {
tags: state.tagReducer
};
};
function matchDispatchToProps(dispatch){
return bindActionCreators({tagSelected: tagSelected}, dispatch);
}
export default connect(mapStateToProps, matchDispatchToProps)(TagListItemDetails);
firstList
export default class TagList extends Component {
handleClicked() {
console.log("firstList Clicked")
browserHistory.push("TagListItemDetails")
}
render() {
return (
<div>
<List id="parent-list-tags" >
<ListItem primaryText="Scene" onClick={this.handleClicked} />
<Divider/>
<ListItem primaryText="Actors" onClick={this.handleClicked} />
<Divider/>
<ListItem primaryText="Emotions" onClick={this.handleClicked} />
<Divider/>
<ListItem primaryText="Actions" onClick={this.handleClicked}/>
<Divider/>
<ListItem primaryText="Objects" onClick={this.handleClicked}/>
<Divider/>
<ListItem primaryText="Compliance" onClick={this.handleClicked} />
</List>
<AddButton />
</div>
)
}
};

The problem is that in the SecondList, you are invoking the handleClick method as soon as the component is loaded. Try removing the parentheses () from the onClick handler. So instead of
<ListItem primaryText="Beach" onClick={this.handleClick()}/>
you can use:
<ListItem primaryText="Beach" onClick={this.handleClick}/>
------------------------------------------------------^^ No parentheses here
One way of passing arguments to a click handler passed as a prop is to use the fat arrow function:
onClick={() => this.props.itemSelected(2)}
// or if you want to pass the event as well:
onClick={(event) => this.props.itemSelected(2, event)}
Also, here is a demo of how to fire two functions on onClick event : http://codepen.io/PiotrBerebecki/pen/YGRQrG

Related

How do I add an 'onClick' event to a mapped data?

{data && data.map((data) => <Cards data={data} key={data._id} />)}
The code checks if there is data and of course if there is, it displays the card component.
I want to add a click event so I could know which of the list of cards retuned in particular is being clicked.
I've done this, it does not work.
{data && data.map((data) => <Cards onClick={click} data={data} key={data._id} />)}
and here is the click function
const click = (e) => {
e.preventDefault();
console.log("clicked");
};
You have a typo onClick and not onCLick
Edit:
You can wrap the <Card/> inside a <div> and add onClick to the div or inside the <Card/> component add onClick to the parent component and pass your click function as a prop

Getting id from an event handler that was passed to a button component in React?

I have an App component that renders a MenuBar component. In that MenuBar, I render ListItems (from material-ui) and pass the following as a prop:
onClick = (e) => {
const id = e.target.id;
console.log(id);
console.log('called');
}
the MenuBar component:
render() {
const onClick = this.props.onClick;
const titles = ["Home", "About", "Docket", "Polls", "News"];
const listItems = titles.map(title =>
<ListItem button id={title} onClick={onClick} key={title}>
<ListItemText primary={title} />
</ListItem>);
return (
<List
component="ul"
className="menu-bar">
{listItems}
</List>
);
}
I want to use this title, which I try to retrieve from the event, so that I can render a Home component, or About component, etc, depending on which ListItem is selected. But when I run this and click randomly on some of the ListItems in my browser, the title is only logged to the console sometimes (seemingly randomly). What is the best way for me to access which ListItem was selected, or why is the console logging the title only sometimes?
Here is what I get in the browser console:
Docket
called
called
Polls
called
News
called
The reason why you don't consistently get id is that the html element triggering the click event is not always what you think. Please see this sandbox for an example. When you click on any of the ListItem, sometimes you get (if you click to the left of where the letter is, based on my trials):
<div class="MuiButtonBase-root-1883 MuiListItem-root-1871 MuiListItem-default-1874 MuiListItem-gutters-1879 MuiListItem-button-1880" tabindex="0" role="button" id="a">...</div>
where the id is present. But other times you get:
<span class="MuiTypography-root-1892 MuiTypography-subheading-1899 MuiListItemText-primary-1889">a</span>
where the id is missing.
A solution to this is to pass title directly to the onClick function:
<ListItem button id={title} onClick={() => onClick(title)}>
...
</ListItem>
Accordingly, the onClick function should be updated as follows:
onClick = (title) => {
console.log(title);
console.log('called');
}
currentTarget is what worked it for me. (instead of just target)
I've read elsewhere that maybe MUI is resulting in unexpected behavior. Similar to what Claire Lin stated, in the Material UI List (and for me, it was nested in a MUI Drawer as well), when clicking on a button, the actual target was different from what I expected. The solution I found is to use the following:
Try e.currentTarget.getAttribute('value') , where "value" is data placed on the ListItem.
Here's how I added it. See "value" being assigned, and then logged below in the onClick. (...I tried to remove most of the extra code, but there is still a bit of superfluous code in there just bc it provides context.)
return (
//removed extra code for brevity
<Drawer
anchor={'left'}
open={drawerOpen}
onClose={toggleDrawerOpen(false)}
>
<List>
{itemsList.map((item, index) => {
const { text, icon, id } = item
return (
<ListItem
button
key={id}
value={index} // <<<< HERE!!!
onClick={(e) => {
console.log(e.currentTarget.getAttribute('value')) // <<<< HERE!!!
setDrawerOpen(false)
}}
>
{icon && <ListItemIcon>{icon}</ListItemIcon>}
<ListItemText primary={text} />
</ListItem>
)
})}
</List>
</Drawer>
...Again, I used "value" and assigned it the "index".
currentTarget is the trick.

react-sortable-hoc. onClick event on <SortableElement/>

const SortableItem = SortableElement(({ i, value}) =>
<ListItem button onClick={this.handleClick(i, value.title)}>
<ListItemText primary={<div className={classes.title}>{value.title}</div>}/>
</ListItem>
);
when I call this SortableItem in SortableContainer and then in render use it, when clicking on one item it call the handleClick function for all elements the same time. What to do?
Call click event like this.
<ListItem button onClick={()=> this.handleClick(i, value.title)}>

NativeBase unable to list only some part of array

So my data is:
[
{"id_categories":1,"name":"One"},
{"id_categories":2,"name":"Two"},
{"id_categories":3,"name":"Three"}
]
And my class to display the list is :
import React, { Component } from 'react';
import { Text } from 'react-native';
import { Container, Content, Card, CardItem, Body, Left,
Right, List, ListItem, } from 'native-base';
export default class ListData extends Component {
render(){
let articles = this.props.data.map(function(items, index){
return(
<List dataArray={items}
renderRow={(item) =>
<ListItem>
<Text>{item}</Text> // this displays the id also
<Text>{item.name}</Text> // this does not display anything
//Only using one of the two <Text> above at a time
</ListItem>
}>
</List>
)
});
return(
<Content>
{articles}
</Content>
)
}
}
I want to be able to show only the name in the list and make it TouchableOpacity and pass the value of the id_categories clicked to another screen. But I'm not able to show the only the name
You don't need to map your array if you use native base list
dataArray contains your array data and renderrow contains a component or custom component.
return (
<List dataArray={this.props.data}
renderRow={(item) =>
<ListItem>
<Text>{item.name}</Text>
</ListItem>
}>
</List>
);
Your item inside map function is already the one you want to process: {"id_categories":1,"name":"One"}.
So inside the map loop you can access name by item.name as follow:
let articles = this.props.data.map(function(item, index) {
// item ={"id_categories":1,"name":"One"},
return(
<List dataArray={"I will skip this one"}
renderRow={(item) =>
<ListItem>
<Text>{item.name}</Text>
</ListItem>
}>
</List>
)
});
EDIT
Just have a look at NativeBase List, and I think this should fit your requirements
let articles = (
<List dataArray={this.props.data}
renderRow={(item) => <ListItem><Text>{item.name}</Text></ListItem>}>
</List>
)
});

How to pass parameters in onClick event bind?

I've set up an onClick event in a ListItem. Then called .bind on the method invoked to pass in the clicked list item's id and name values.
The following SO question suggested using bind but it seems adding the onCLick event to the ListItem breaks the list binding.
Before adding the click event the list span binding to the asset.name is working as expected and the list is populated.
Also if I try onClick={this._onAssetSelected() with no parameters the click event doesn't work.
Question:
How can you pass parameters in an onClick event bind in JSX?
List definition:
<List selectable={true} selected={0}>
{
this.state.data.map(function (asset) {
return (
<ListItem justify="between" onClick={this._onAssetSelected.bind(this, asset.name, asset.id)} >
<span>{asset.name}</span>
</ListItem>
);
})
}
</List>
Method called from the click event:
_onAssetSelected(assetName, assetID) {
console.log(assetName);
console.log(assetID);
}
You can do this. Define an anonymous function as the callback, inside which you call your method with the parameters. Hop ut helps!
<List
selectable={true}
selected={0}>
{
this.state.data.map(function (asset) {
return (
<ListItem
justify="between"
onClick={(e) => this._onAssetSelected(asset.name, asset.id, e)} >
<span>{asset.name}</span>
</ListItem>
);
})
}
</List>

Resources