2

I have few Card component from material UI, each of them contain an EDIT button and there is a handler available for it, they are being added dynamically using Map traversing (In example, i have just hard coded two of them).

Now, i am trying to make the card editable in button click but not able to find out how to get to know from which Card, event is triggered and then make "Typography" of that editable to 'TextField'.

 <CardContent> <Typography>ID: '1'</Typography> <Typography className={classes.title} color="textSecondary" gutterBottom > Word of the Day </Typography> <Typography>Name: 'RAAM'</Typography> <Typography>Blood group: 'AB+'</Typography> <Typography>"Patient Ram is having bloodgroup AB+"</Typography> </CardContent> <CardActions> <Button size="small" onClick={click}> Edit </Button> </CardActions> <CardContent> 

Here is my codeSandbox example CodeSandbox

6
  • can you include also in the post the click method? Commented Sep 28, 2020 at 16:49
  • @vsync Its pretty basic so did not post here, though its available in codesandbox link. Commented Sep 28, 2020 at 16:51
  • You must have some identifier for each card.. you need to pass it to click method. you should then update the state accordingly and then react to the state change to update the DOM, make that specific card editable. Commented Sep 28, 2020 at 16:51
  • Do you know how to work with react state? useState for example? Commented Sep 28, 2020 at 16:53
  • How come your card has 2 cards inside of it..? this is not proper Commented Sep 28, 2020 at 16:54

2 Answers 2

3

The usual solution is to have the card pass back some identifying information or an object that you've passed it, since there's very little you can do with the React element.

If you want the DOM element, it's the currentTarget property of the event object that your click function receives.

Here's a simple example showing both with stand-ins for Card and its parent, in this case the Card component returns the id you pass it as a second argument to the click function:

"use strict"; const cards = Array.from(Array(5), (_, index) => ({ id: index + 1, value: `Card ${index + 1}` })); function Parent() { const click = (evt, id) => { console.log(`evt.currentTarget.tagName = ${evt.currentTarget.tagName}, id = ${id}`); }; return cards.map(({id, value}) => <Card key={id} value={value} onClick={evt => click(evt, id)} /> ); } function Card({value, onClick}) { return <div onClick={onClick}>{value}</div>; } ReactDOM.render(<Parent />, document.getElementById("root"));
<div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.0/umd/react-dom.production.min.js"></script>

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

2 Comments

I like this approach better: onClick={click(id)} and const click = id => e => ...
@vsync - To each their own. :-) They do the same thing in the end.
0
import React, { useRef } from "react"; import { makeStyles } from "@material-ui/core/styles"; import Card from "@material-ui/core/Card"; import CardActions from "@material-ui/core/CardActions"; import CardContent from "@material-ui/core/CardContent"; import Button from "@material-ui/core/Button"; import Typography from "@material-ui/core/Typography"; const useStyles = makeStyles({ root: { minWidth: 275 }, bullet: { display: "inline-block", margin: "0 2px", transform: "scale(0.8)" }, title: { fontSize: 14 }, pos: { marginBottom: 12 } }); export default function OutlinedCard() { const refs = useRef([]); const classes = useStyles(); const click = (event) => { const { currentTarget: { id = "" } = {} } = event; const clickedCard = refs.current[id]; // This is the card whose button got clicked console.log(clickedCard); }; const createRefs = (id, node) => (refs.current[id] = node); return ( <Card className={classes.root} variant="outlined"> <CardContent ref={(node) => {createRefs('card_1', node)}}> <Typography>ID: '1'</Typography> <Typography className={classes.title} color="textSecondary" gutterBottom > Word of the Day </Typography> <Typography>Name: 'RAAM'</Typography> <Typography>Blood group: 'AB+'</Typography> <Typography>"Patient Ram is having bloodgroup AB+"</Typography> </CardContent> <CardActions> <Button size="small" id="card_1" onClick={click}> Edit </Button> </CardActions> <CardContent ref={(node) => {createRefs('card_2', node)}}> <Typography>ID: '2'</Typography> <Typography className={classes.title} color="textSecondary" gutterBottom > Word of the Day </Typography> <Typography>Name: 'RAAM'</Typography> <Typography>Blood group: 'AB+'</Typography> <Typography>"Patient Ram is having bloodgroup AB+"</Typography> </CardContent> <CardActions> <Button size="small" id="card_2" onClick={click}> Edit </Button> </CardActions> </Card> ); } 

2 Comments

She doesn't have a class in her code... she uses functional React, hence - this doesn't help her
@vsync okay, updated code as per her. ID's are hardcoded but it should be dynamic incase she uses array to render cards.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.