How to send card id to the menu items using reactjs? - reactjs

My objective is to pass the id for handleClick function, If i click on the 3 dots of the respective card then it should reflect particular card id. Can anyone help me in giving id for handle Click arrow function.
Here is the code:
state = { menu: null };
handleClick = (e) => {
this.setState({ menu: e.target });
};
handleClose = () => {
this.setState({ menu: null });
};
{Data.map(user => (
<CardHeader
key={user.id}
className={classes.header}
avatar={<Avatar aria-label="recipe">R</Avatar>}
action={
<div className={this.state.menu && classes.menu}>
<IconButton
id="simple-menu"
className={classes.showIcon}
aria-label="settings"
aria-controls="simple-menu"
onClick={this.handleClick}
>
<MoreVertIcon />
</IconButton>
<Menu
style={{ marginTop: "35px" }}
id="simple-menu"
keepMounted
anchorEl={this.state.menu}
open={Boolean(this.state.menu)}
onClose={this.handleClose}
>
<MenuItem onClick={this.handleClose}>View</MenuItem>
<MenuItem onClick={this.handleClose}>hide</MenuItem>
</Menu>
</div>
}
title={user.title}
subheader={user.subheader}
/>
))}
here is the sample one

You can bind the function and pass the id to it. Like
handleClick = (id, e) => {
console.log(id)
this.setState({ menu: e.target, id: id });
};
<IconButton
id="simple-menu"
className={classes.showIcon}
aria-label="settings"
aria-controls="simple-menu"
onClick={this.handleClick.bind(this, user.id)}
>
<MoreVertIcon />
</IconButton>
or instead of binding the function you can create a new arrow function and pass the id like this:
<IconButton
id="simple-menu"
className={classes.showIcon}
aria-label="settings"
aria-controls="simple-menu"
onClick={(e) => this.handleClick(user.id, e)}
>
<MoreVertIcon />
</IconButton>
You can save the id in states and then use it in the menu component to perform further actions

Here is a trick solution for that kind of situations. Also this is most performant solution. You won't need to create arrow function instance for every re-render or each React node.
<IconButton
id="simple-menu"
className={classes.showIcon}
aria-label="settings"
aria-controls="simple-menu"
onClick={this.handleClick}
data-user-id={user.id} // Define your user id as native data attribute
>
And then get data attribute of your current clicked element.
handleClick = (e) => {
const { userId } = e.currentTarget.dataset; // Get your data-user-id value as string
console.log(Number(userId));
this.setState({ menu: e.target, id: Number(userId) }); // Convert to number and save to state
};
So you can create your own scenarios up to your depends.
In this case, also you might want to learn event bubbling logic to understand the difference between target and currentTarget use case.
Also you can check it out for more information about data-* attributes.
https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

Related

How to add onClick button to any tabs in MUI?

I wanna add onClick in button (like swap languages in google translate) to any tabs. I want like click Swap languages in google translate to other languages like en -> es to es -> en.
const [value_s, setValue_s] = useState('one');
const [value_t, setValue_t] = useState('four');
const handleChange_s = (event, newValue) => {
setValue_s(newValue);
};
const handleChange_t = (event, newValue) => {
setValue_t(newValue);
};
<Tabs
value={value_s}
onChange={handleChange_s}
>
{languages.map((item) => (
<Tab key={item} label={item.Name} onClick={() => { setSource(item.langcode) }} />
))}
</Tabs>
{/* Swap languages Button*/}
<Tooltip title="Swap languages">
<IconButton
onClick={() => { setSource(target), setTarget(source) }}
>
<SwapHorizIcon />
</IconButton>
</Tooltip>
<Tabs
value={value_t}
onChange={handleChange_t}
textColor="secondary"
indicatorColor="secondary"
>
{languages.map((item) => (
<Tab key={item} label={item.Name} onClick={() => { setTarget(item.langcode) }} />
))}
</Tabs>
You can add a value prop to the Tab component. Which will allow you to toggle on the value, instead the index.
For this we need to change the initial states of the source and target.
const [value_s, setValue_s] = useState("en");
const [value_t, setValue_t] = useState("es");
Now to can add the value prop to the Tab component, same by the target Tab
<Tabs value={value_s} onChange={handleChange_s}>
{languages.map((item) => (
<Tab
key={item}
value={item.langcode} // the value
label={item.Name}
onClick={() => {
setSource(item.langcode);
}}
/>
))}
</Tabs>
Create a handleSwap function for the button
const handleSwap = () => {
setValue_s(value_t);
setValue_t(value_s);
};
Which we can use like this
<IconButton onClick={handleSwap}>

Open a modal (or dialogue) from a dropdown asking the user if they would like to take an action

I would like to open a modal (or dialogue) when a user selects an option from a dropdown menu.
Eventually there will be a few options in the dropdown, and different dialogues/modals will be called and rendered depending on which dropdown option has been clicked. For now - how do I get the modal/dialogue to open with dropdown menu events?
I'm currently using the handleClose handler to attempt to open a dialogue since that event should be easy to grab and use right out of the docs for MUI Menu and MenuItem.
The origination call to the DropdownMenu component (which works well and shows the dropdown menu) occurs in a table through the click of an icon
<DropdownMenu options={['Show modal or dialogue to the user']}>
<MoreHorizIcon />
</DropdownMenu>
The DropdownMenu component (also working well itself, except for not triggering the dialogue/modal) looks like this
interface IProps extends Omit<unknown, 'children'> {
children: any;
options: string[];
}
const ITEM_HEIGHT = 48;
const DropdownMenu = ({ children, options }: IProps) => {
const [anchorEl, setAnchorEl] = React.useState<null | HTMLElement>(null);
const open = Boolean(anchorEl);
const handleClick = (event: React.MouseEvent<HTMLElement>) => {
setAnchorEl(event.currentTarget);
};
const showModal = () => {
return (
<AlertDialog />
)
}
const handleClose = () => {
//the native alert dialogue works well
alert('I want to show a dialog or modal the same way this alert shows up and ask the user if they are sure they want to delete something')
//why isn't the custom alert dialog being called?
showModal();
setAnchorEl(null);
};
return (
<div>
<IconButton
aria-label="more"
id="more-button"
aria-controls="long-menu"
aria-expanded={open ? 'true' : undefined}
aria-haspopup="true"
onClick={handleClick}
>
{children}
</IconButton>
<Menu
id="dropdownmenu"
MenuListProps={{
'aria-labelledby': 'more-button'
}}
anchorEl={anchorEl}
open={open}
onClose={handleClose}
PaperProps={{
style: {
maxHeight: ITEM_HEIGHT * 4.5,
width: '20ch'
}
}}
>
{options.map(option => (
<MenuItem key={option} onClick={handleClose} >
{option}
</MenuItem>
))}
</Menu>
</div>
);
};
export default DropdownMenu;
And the example starter dialogue I am using to get the ball rolling looks like this
const AlertDialog = () => {
const [open, setOpen] = React.useState(true);
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{"Sweet Filler Dialog"}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Are you sure?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>NO</Button>
<Button onClick={handleClose} autoFocus>
YES
</Button>
</DialogActions>
</Dialog>
</div>
);
}
You can use a state variable to trigger the modal in the DropdownMenu component, whenever you wanted to show the dialog/modal.
const [isModalOpen, setIsModalOpen] = React.useState(false);
and then in the handleClose, you can update the modal state to open the modal.
const handleClose = () => {
setIsModalOpen(true)
setAnchorEl(null);
};
Then somewhere in your JSX of DropdownMenu, you can conditionally render the AlertDialog component like this
{isModalOpen ? <AlertDialog open={isModalOpen} setOpen={setIsModalOpen} /> : null}
Finally, update your AlertDialog component to use props to handle the closing of the modal.
const AlertDialog = ({ open, setOpen }) => {
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<DialogTitle id="alert-dialog-title">
{"Sweet Filler Dialog"}
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Are you sure?
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>NO</Button>
<Button onClick={handleClose} autoFocus>
YES
</Button>
</DialogActions>
</Dialog>
</div>
);
}

How to make links work with card-img-overlay React

I'm having an issue on my project. I created a card-img-overlay to display icons over an image. If you click on the entire image you are redirected to a post. I would like to make the like and share icons clickable.
My project is in Reactjs. I am displaying images and videos from Reddit API.
Thank you for your help.
id,
slugTitle,
title,
url_overridden_by_dest,
author,
preview,
}) => {
const [isVideo, setIsVideo] = useState(false);
useEffect(() => {
if (preview) setIsVideo(preview.split('.').pop() === 'mp4');
}, [preview]);
const history = useHistory();
const goToPage = () => {
history.push(`/Post/${id}/${slugTitle}`);
};
return (
<Card
inverse
onClick={goToPage}
style={{
cursor: 'pointer',
}}
>
{isVideo && (
<video autoPlay="false" loop width="100%" src={preview}>
<track default kind="captions" />
</video>
)}
{!isVideo && (
<CardImg top width="100%" src={url_overridden_by_dest} alt={title} />
)}
<CardImgOverlay className="hideinfos">
<CardText className="w-100 d-flex justify-content-between">
<div>
<VscAccount className="mr-2" size={20} />
{author}
</div>
<div>
<LikeButtonhp
className="mr-2 card-link"
size={20}
style={{
position: 'relative',
}}
/>
<BiShareAlt size={20} />
</div>
</CardText>
</CardImgOverlay>
</Card>
);
};
You'll need to put onClick handlers on your LikeButtonhp and BiShareAlt components, and use event.stopPropagation() to stop the event from bubbling up to the <Card />:
<BiShareAlt
size={20}
onClick={event => {
event.stopPropagation();
// Do stuff for share click
}}
/>
You may need to alter the BiShareAlt and LikeButtonhp components to support an onClick prop also, for example if they render a <button> element it may look like this:
const BiShareAlt = ({ onClick }) => (
<button onClick={onClick}>
Share
</button>
);
export default BiShareAlt;
In my onClick, I added an e.stopPropagation(); and it solves my problem. Now I can click on the heart icon and it works. It stops the onClick set up on my image (parent).
function LikeButtonhp() {
const [liked, setLiked] = useState(false);
return (
<Button
outline
color="link"
className="likebutton"
onClick={(e) => {
e.stopPropagation();
setLiked(!liked);
}}
style={{ color: 'white' }}
>
{liked ? <BsHeartFill size={20} /> : <BsHeart size={20} />}
</Button>
);
}

Trigger modal from dropdown menu click event antd

So i have a <Modal/> which is controlled by a state Visible, i want to be able to change the state of this modal from a dropdown menu inside a table row from Antd using SetVisible but i cannot find a way to do it, any suggestions?
<Table // antd table
loading={Boolean(!data)}
rowKey={'id'} expandable={expandable}
pagination={{pageSize: 5}}
columns={columns}
dataSource={data}
/>
render: (text, record) => ( // fragment from column object, which contain in column that'll be rendered
<Space size="middle">
<Dropdown overlay={() => DropMenu()}> //Where the dropdown compoennt is being called
<a className="ant-dropdown-link" onClick={e => e.preventDefault()}>
Mais Opções <DownOutlined />
</a>
</Dropdown>
</Space>
const DropMenu = () => { //Dropdown Component
return (
<Menu>
<Menu.Item>
<a target="_blank" rel="noopener noreferrer" href="http://www.taobao.com/"> // Here I'll trigger the modal
trigger modal
</a>
</Menu.Item>
</Menu>
)
};
I actually realized that antd has a Modal.confirm() which is a function that renders a confirmation modal with an ok and cancel button which you handle your own way.
<Menu.Item danger>
<span onClick={() => confirm({id: record.id})}>Delete</span>
</Menu.Item>
function confirm({name, id}) {
Modal.confirm({
title: 'Confirm',
icon: <ExclamationCircleOutlined />,
content: 'Are you sure you want to delete this user??',
okText: 'Confirmar',
cancelText: 'Cancelar',
onOk: (close) => { ...handling deletion }
)}
}
you can also try
<Menu
items={[
{
key: 1,
label: <div onClick={() => edit()}>edit</div>,
},
]}
/>

Material-UI - Click on Menu Button opens all Menu Items available

I'm having a small issue with Material-UI. And it is that everytime I click on a button to open an specific dropdown/menuItem it opens all the Dropdown/Items available in the AppBar. I did change the 'open' variable name, but it just gives me an error instead. The Material-UI documentation does not includes examples two or more dropdown menus.
Here's my code:
class MaterialTest extends Component {
state = {
anchorEl: null
};
handleClick = event => {
this.setState({ anchorEl: event.currentTarget });
};
handleClose = () => {
this.setState({ anchorEl: null });
};
render() {
const { anchorEl } = this.state;
const open = Boolean(anchorEl);
return (
<div style={mainDiv}>
<AppBar position="static" color="default" style={barStyle}>
<Toolbar style={toolStyle}>
<NavLink to="/">
<Button>Home</Button>
</NavLink>
<Button
aria-owns={anchorEl ? 'product-shipping' : null}
aria-haspopup="true"
onClick={this.handleClick}
>
Product Shipping
</Button>
<Menu
id="product-shipping"
anchorEl={anchorEl}
open={open}
onClose={this.handleClose}
>
<NavLink to="viewAll">
<MenuItem onClick={this.handleClose}>View Latest SKUs</MenuItem>
</NavLink>
<NavLink to="addSku">
<MenuItem onClick={this.handleClose}>Add New SKU</MenuItem>
</NavLink>
<MenuItem onClick={this.handleClose}>Import / Export</MenuItem>
<MenuItem onClick={this.handleClose}>Tables</MenuItem>
</Menu>
<Button
aria-owns={anchorEl ? 'inventory' : null}
aria-haspopup="true"
onClick={this.handleClick}
>
Inventory
</Button>
<Menu
id="inventory"
anchorEl={anchorEl}
open={open}
onClose={this.handleClose}
>
<NavLink to="viewInventory">
<MenuItem onClick={this.handleClose}>Site Inventory</MenuItem>
</NavLink>
<MenuItem onClick={this.handleClose}>
Warehouse Inventory
</MenuItem>
<MenuItem onClick={this.handleClose}>Add New Inventory</MenuItem>
</Menu>
<Button
aria-owns={anchorEl ? 'vendor-information' : null}
aria-haspopup="true"
onClick={this.handleClick}
>
Vendor Information
</Button>
</Toolbar>
</AppBar>
</div>
);
}
}
Any Ideas? Thank you
It might be because all the menus are being opened when anchorEl is set. The open prop is only checking for Boolean(anchorEl) and they all share this same state (so whenever it returns true they all open)
You could try setting an anchorEl2, anchorEl3 and so on in the state and change each Menu and Button accordingly.

Resources