Niklas
Niklas

Reputation: 1798

How to make Card component clickable?

I use the Ant Design for my WebApp. For the Card, there's a hoverable prop that make the card seams clickable but there's no onClick prop. How do I make it really clickable?

This is my Code:

import React, { Component } from 'react';
import { Card, Avatar, Icon, Button, Divider } from 'antd';
import EventDetailsDrawer from '../ui/EventDetailsDrawer';

const { Meta } = Card;

class EventCard extends Component {

render() {
    return (
        <div onClick={alert("Hello from here")}>
            <Card
                hoverable
                cover={<img alt="example" src="https://assetsnffrgf-a.akamaihd.net/assets/m/1102015169/univ/art/1102015169_univ_lsr_lg.jpg" />}
                bodyStyle={{ marginBottom: "-5px" }}
                >
                    <Meta
                        //avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
                        avatar={<Button type="primary" shape="circle-outline">{this.props.owner}</Button>}
                        title={this.props.title}
                        description={this.props.descp}
                    />
                    <Divider style={{ marginLeft: "0px" }}></Divider>
                    <p><Icon type="clock-circle" style={{ fontSize: "15px", color: "#1890FE" }} theme="outlined" /><span style={{ marginLeft: "15px" }} />{this.props.date}</p>
                    <p><Icon type="environment" style={{ fontSize: "15px", color: "#1890FE" }} theme="outlined" /><span style={{ marginLeft: "15px" }} />{this.props.location}</p>
        </Card>
                    <EventDetailsDrawer></EventDetailsDrawer>
        </div>
                );
            }
        }

export default EventCard

I try to make a dive (around the Card) clickable, but the Code runs immediately after the app is loaded, since I pack each card into a list item. How to make Card component clickable?

Thanks for your answer :)

Upvotes: 11

Views: 65794

Answers (8)

Adam Cox
Adam Cox

Reputation: 3681

I came here with a similar question. What worked for me is to wrap the <Card> with a <Link> component. Also, setting the hoverable property on the card will give it an effect that has it appear "clickable". For example:

<Link to={'/customer/list'}>
   <Card hoverable>

      // ... removed for brevity...

   </Card>
</Link>

Upvotes: 9

ACV
ACV

Reputation: 10560

This works well for me:

  <Card className={classes.root}>
      <CardActionArea
        onClick={(evt) => {
          console.log(evt.target);
          sayHi(evt);
        }}
      >
        <CardContent>
          <Typography variant="h5" component="h2">
            {props.job.label}
          </Typography>
        </CardContent>
      </CardActionArea>
      <CardActions></CardActions>
    </Card>

and sayHi is

  function sayHi(props) {
    history.push({
      pathname: "/another-page/",
      state: { jobId: props.job.id },
    });
  }

Upvotes: 0

Devo
Devo

Reputation: 1124

Since the antd Card already supports onClick, you can pass this onClick to your custom property like below:

// EventCard.js
import React from 'react';
import PropTypes from './propTypes';
import 'antd/dist/antd.css';
import { Card } from 'antd';

const { Meta } = Card;

const EventCard = ({
    myOnClick,
    ...restProps
}) => {
    return (
        <Card
            hoverable
            bodyStyle={{ marginBottom: "-5px" }}
            cover={<img alt="example" src="https://assetsnffrgf-a.akamaihd.net/assets/m/1102015169/univ/art/1102015169_univ_lsr_lg.jpg" />}
            onClick={() => myOnClick()}
        >
            <Meta 
                title={this.props.title}
                description={this.props.descp} />
        </Card>
    );
};

EventCard.propTypes = {
    myOnClick: PropTypes.func,
};

export default EventCard;

Where propTypes is:

// propTypes.js
import PropTypes from 'prop-types';

export default {
  ...PropTypes,
  ID: PropTypes.oneOfType([PropTypes.string, PropTypes.number]).isRequired,
  component: PropTypes.oneOfType([PropTypes.string, PropTypes.func]),
  date: PropTypes.oneOfType([PropTypes.instanceOf(Date), PropTypes.string]),
};

Then you can use it like:

myClickHandler = (params) => {
    console.log("Click!!!");
});

render() {
    return (
        <EventCard myOnClick={()=> this.myClickHandler("any parameters")} />
    );
}

Upvotes: 1

Georg
Georg

Reputation: 63

maybe this will help:

youHandleClickFunc = (params) => {
console.log('you need params from Card', params)
}

render() {
        return (
          <Card handleClick={()=> this.youHandleClickFunc(param)}/>
        )
}

Upvotes: -1

Yichz
Yichz

Reputation: 9681

Keep in mind make a div clickable is a very bad practice in terms of accessibility, because without mouse, you cannot tab to the card nor use enter or space to click the card.

My recommendation would be wrap the card with an unstyled button, so you can take all the advantages of a button (click, tab, keyboard support)

    import React, { Component } from 'react';
    import { Card, Avatar, Icon, Button, Divider } from 'antd';
    import EventDetailsDrawer from '../ui/EventDetailsDrawer';

    const { Meta } = Card;

    class EventCard extends Component {

    render() {
        return (
            <button onClick={alert("Hello from here")} className="unstyled-button">
                <Card />
            </button>
                    );
                }
            }

    export default EventCard

css

 .unstyled-button {
       border:none;
    }

Upvotes: 0

Sidonai
Sidonai

Reputation: 3696

Try this, onClick expects a function, and is invoking when render() is executed.

import React, {Component} from 'react';
import {Card, Avatar, Icon, Button, Divider} from 'antd';
import EventDetailsDrawer from '../ui/EventDetailsDrawer';

const {Meta} = Card;

class EventCard extends Component {
    render() {
        return (
            <div onClick={() => {alert("Hello from here")}}>
                <Card
                    hoverable
                    cover={<img alt="example"
                            src="https://assetsnffrgf-a.akamaihd.net/assets/m/1102015169/univ/art/1102015169_univ_lsr_lg.jpg"/>}
                            bodyStyle={{marginBottom: "-5px"}}
                >
                    <Meta
                        avatar={<Button type="primary" shape="circle-outline">{this.props.owner}</Button>}
                        title={this.props.title}
                        description={this.props.descp}
                    />
                    <Divider style={{marginLeft: "0px"}}></Divider>
                    <p>
                        <Icon type="clock-circle" style={{fontSize: "15px", color: "#1890FE"}} theme="outlined"/>
                        <span style={{marginLeft: "15px"}}/>
                        {this.props.date}
                    </p>
                    <p>
                        <Icon type="environment" style={{fontSize: "15px", color: "#1890FE"}} theme="outlined"/>
                        <span style={{marginLeft: "15px"}}/>
                        {this.props.location}
                    </p>
                </Card>
                <EventDetailsDrawer></EventDetailsDrawer>
            </div>
        );
    }
}

export default EventCard

Upvotes: 1

Szymon Pancerz
Szymon Pancerz

Reputation: 237

There is no possible, to make onClick here. You need to call an onClick event inside the Card component. Then if you need to pass some props, or use logic, just pass the function/content in the prop to Card. Something like that - <Card handleClick={this.handleClickMethod} />. Then inside Card component you can call the handleClick function.

Hope that helped you

Upvotes: -1

Thiago Murakami
Thiago Murakami

Reputation: 995

Notice that what you are attaching to the div's onClick listener is the value returned by alert and not actually a function that should be run whenever the div is clicked.

Try changing this:

<div onClick={alert("Hello from here")}>

To this:

<div onClick={() => alert("Hello from here")}>

Upvotes: 14

Related Questions