reactstrap tooltip dynamic id

10,180

Solution 1

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

Solution 2

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;

Solution 3

Create a new component in modular or component directory and paste this code

import React, { useState } from "react";
import { Tooltip } from "reactstrap";

const TooltipItem = props => {
    const { position='top', id } = props;
    const [tooltipOpen, setTooltipOpen] = useState(false);

    const toggle = () => setTooltipOpen(!tooltipOpen);

    return (
        <span>
      <span id={"tooltip-" + id}>
            {props.children}
      </span>
      <Tooltip
          placement={position}
          isOpen={tooltipOpen}
          target={"tooltip-" + id}
          toggle={toggle}
      >
          {props.title}
      </Tooltip>
    </span>
    );
};


export default TooltipItem;

Now import and use this tooltip component

import TooltipItem from "../Tooltip";

 <TooltipItem id={'edit' + data.id} title={'Edit Store'}>
    <i className="fas fa-edit pointer" onClick={() => this.onEditClick(data)}/>
  </TooltipItem>
Share:
10,180
Priyank Thakkar
Author by

Priyank Thakkar

• 9 years of experience in developing &amp; designing thin client and thick client applications using Java, Spring MVC, Hibernate, HTML, CSS3, jQuery, JavaScript, Eclipse Rich Client Platform, C#, .net framework, Windows Presentation Foundation (WPF) • Hands on experience on front-end UI frameworks like AngularJS, Foundation 6 and added skills like NodeJS and ExpressJS via web based trainings • Mentored newly inducted members of the team by providing them product knowledge &amp; provided technical trainings and grooming • Familiar with Waterfall and Agile methodologies. • Have been part of requirement brainstorming, design and development of applications, end to end development • Conduct technical interviews and get new developers for the team • Having passion for learning new things and enjoys a variety of work - ambitious and inquisitive

Updated on June 19, 2022

Comments

  • Priyank Thakkar
    Priyank Thakkar almost 2 years

    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

  • Salman Malik
    Salman Malik almost 2 years
    You saved me hours. This works with <UncontrolledTooltip> as well. kudos.
  • Salman Malik
    Salman Malik almost 2 years
    This doesn't address the actual context.