Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

reactstrap tooltip dynamic id

I am developing a react application and using reactstrap.

I am using Tooltip Component of reactstrap which requires a target attribute, a value of target element's id. This id is being geneated dynamically and seems reactstrap tooltip doesn't like it.

Component looks like:

MovieCard.jsx

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Col, Card, CardImg, CardBody, CardTitle, CardSubtitle, CardText, Button, Tooltip } from 'reactstrap';
import { LimitedTextTitle } from '../custom-styled/CustomStyledComponents';

class MovieCard extends Component {  

  constructor (props) {
    super(props);
    this.state = {
      open: false
    };
    this.toggle = this.toggle.bind(this);
  }

  toggle () {
    this.setState({
      open: !this.state.open
    })
  }

  render () {
    const { imdbID, Title, Year, Rated, Plot, Country, Poster } = this.props.movie;

    return (
  <Col md="4">
    <Card>
      <CardImg
        top
        width="100%"
        src={Poster}
        alt="blah"
      />
    </Card>
    <CardBody>
      <CardTitle>
        <LimitedTextTitle id={imdbID}>
          {`${Title} - (${Year})`}
        </LimitedTextTitle>
        <Tooltip placement='top' target={imdbID} isOpen={this.state.open} toggle={this.toggle}>
          {Title}
        </Tooltip>
      </CardTitle>
      <CardSubtitle>{`Rated: ${Rated} Country: ${Country}`}</CardSubtitle>
      <CardText>{Plot}</CardText>
      <Button>Read More</Button>
    </CardBody>
  </Col>
);
  }
}

MovieCard.propTypes = {
  movie: PropTypes.object.isRequired // eslint-disable-line
};

export default MovieCard;

Any suggestions?

react vesion 16.2.0

reactstrap 5.0.0-alpha.4

like image 477
Priyank Thakkar Avatar asked Jan 23 '18 15:01

Priyank Thakkar


2 Answers

Was dealing with a similar problem.

Adding the code as an answer because i cannot add a comment above...

Hope it will help you or anyone else who will come across this question.

Description: Use reactstrap tooltip for elements that are getting generated dynamically.

import React from 'react';
import ReactDOM from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import { Button, Tooltip } from 'reactstrap';

class App extends React.Component {
  state = {};

  toggle = targetName => {
    if (!this.state[targetName]) {
      this.setState({
        ...this.state,
        [targetName]: {
          tooltipOpen: true
        }
      });
    } else {
      this.setState({
        ...this.state,
        [targetName]: {
          tooltipOpen: !this.state[targetName].tooltipOpen
        }
      });
    }
  };

  isToolTipOpen = targetName => {
    return this.state[targetName] ? this.state[targetName].tooltipOpen : false;
  };

  render() {
    return (
      <div>
        {[1, 2, 3, 4, 5, 6].map((x, i) => (
          <div key={`div-${i}`}>
            <Button color="link" id={`btn-${i}`}>
              {x}
            </Button>
            <Tooltip
              placement="right"
              isOpen={this.isToolTipOpen(`btn-${i}`)}
              target={`btn-${i}`}
              toggle={() => this.toggle(`btn-${i}`)}>
              Hello world!
            </Tooltip>
          </div>
        ))}
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('root'));

react: 16.9.0

reactstrap: 8.0.1

https://codesandbox.io/embed/angry-taussig-fup7i?fontsize=14

like image 88
Meir Keller Avatar answered Oct 21 '22 13:10

Meir Keller


EUREKA I GOT IT!!! Building on Meir Keller's answer, there's no need to check if that state for the tooltip already exist. If it doesn't exist, it's false by default...

So long as state is defined, even if it's an empty state, this works.

This is using reactstrap's Popover, but it's the same concept.

import React, { Component, Fragment } from 'react';
import './App.css';
import 'bootstrap/dist/css/bootstrap.min.css'
import { Container, Row, Col, Input, Button, Popover } from 'reactstrap';

class App extends Component {
  state = {};

  toggle = (target) => {
    // console.log(typeof target) // make sure this is a string
    this.setState({
      ...state,
      [target]: !this.state[target]
    });
  };

  render() {
    return (
      <Container>
      {["Hello", "Greetings"].map((name) => (

      <Row>
      <Fragment>
          <Button id={name} type="button">{name}</Button>
          <Popover placement="right" 
          isOpen={this.state[`${name}`]} 
          target={name}
          toggle={() => this.toggle(`${name}`)}>
          <PopoverBody>
            You've got mail. Did you know?
            </PopoverBody>
            </Popover>
            </Fragment>
      </Row>
      ))}
      </Container>
    );
  }
}

export default App;
like image 4
hoohoo-b Avatar answered Oct 21 '22 11:10

hoohoo-b