React Semantic UI hide popup while click on another popup - javascript

I am using react semantic ui in my application. I am using semantic Popup to show tooltip.
Problem facing:- When I click on popup button previous open Popup are not closing automatically.
const PopupExample = () => (
<div>
<Popup
trigger={<Button icon>Click me</Button>}
content='Content 1'
on='click'
/>
<Popup
trigger={<Button icon>click me1</Button>}
content='Content 2'
on='click'
/>
</div>
)
export default PopupExample

Unfortunately, this is a unsolved so far in semantic-ui-react as you can see here: https://github.com/Semantic-Org/Semantic-UI-React/issues/3006
You can maybe use hover instead of click and add hoverable prop.

This is how we can achieve this:-
class PopUpContainer extends Component {
constructor(props) {
super(props);
this.state = {
popupStatus: {
popup1: false,
popup2: false
}
};
}
handleOpen = (keyValue) => {
let status = {
popup1: false,
popup2: false
}
status[keyValue] = true;
this.setState({ popupStatus: status });
}
handleClose = () => {
let status = {
popup1: false,
popup2: false
}
this.setState({ popupStatus: status });
}
render() {
return (
<div className = "button-container" >
<Popup
trigger={<button>Click me1</button>}
content={data.message}
position='bottom left'
on='click'
open={isOpen}
onOpen={() => handleOpen("popup1")}
onClose={handleClose}/>
<Popup
trigger={<button>Click me2</button>}
content={data.message}
position='bottom left'
on='click'
open={isOpen}
onOpen={() => handleOpen("popup2")}
onClose={handleClose}/>
</div>
);
}
};

Related

how fix selected permanently ReactJS

I would like to explain my problem of the day.
the code works correctly ,
the only problem is
when i click on my navbar to select a tab ,
my activeclassname works fine except that when i click elsewhere on the same page i lose my activeclassname
I would like him to be active permanently
Do you have an idea of how to fix this?
class MainHome extends Component {
constructor(props) {
super(props);
this.state = {
};
// preserve the initial state in a new object
this.toggle = this.toggle.bind(this);
this.cgtChange1= this.cgtChange1.bind(this);
this.cgtChange2= this.cgtChange2.bind(this);
}
cgtChange1() {
console.log('bière clicked')
this.setState({
cgt : 1
})
}
cgtChange2() {
console.log('cocktails clicked')
this.setState({
cgt :2
})
}
render() {
let addedItems = this.props.items.length ?
(
this.props.items.filter(item => item.ctg === this.state.cgt).map(item => {
return (
<div key={item.id}>
{item.title}
</div>
)
})) :
(
<div></div>
)
return (
<div>
<Header text='Carte'/>
<NavBar
onClick1={this.cgtChange1}
onClick2={this.cgtChange2}
/>
{addedItems}
</div>
)
}
}
NavBar
export default class FocusOnSelect extends Component {
render() {
return (
<div>
<button onClick={this.props.onClick1}
activeClasseName="selected" className='inactive' > Bières
</button>
</div>
<div >
<button onClick={this.props.onClick2} activeClasseName="selected" className='inactive' > Cocktails </button>
</div>
</div>
);
}
}

Creating show and hide sections with buttons in reactjs

I have three buttons that when clicking show and individual div but this is done in reactjs
import React, { Component } from 'react';
export class ModeExtended extends Component {
constructor() {
super();
this.busButton = this.busButton.bind(this);
this.trainButton = this.trainButton.bind(this);
this.tramButton = this.tramButton.bind(this);
this.state = {
isHidden: false,
}
}
busButton(){
console.log('Bus Button Was Pressed');
this.setState((prevState) => {
return{
isHidden: !prevState.isHidden
};
});
}
trainButton(){
console.log('Train Button Was Pressed');
this.setState((prevState) => {
return{
isHidden: !prevState.isHidden
};
});
}
tramButton(){
console.log('Tram Button Was Pressed');
this.setState((prevState) => {
return{
isHidden: !prevState.isHidden
};
});
}
render() {
return (
<div>
<h5>Mode Extended</h5>
<button onClick={this.busButton}>Bus</button>
<button onClick={this.trainButton}>Train</button>
<button onClick={this.tramButton}>Tram</button>
{this.state.isHidden && (
<div>
<h6>You can show Bus Data Now....</h6>
</div>
)}
{this.state.isHidden && (
<div>
<h6>You can show Train Data Now....</h6>
</div>
)}
{this.state.isHidden && (
<div>
<h6>You can show Tram Data Now....</h6>
</div>
)}
</div>
)
}
}
export default ModeExtended
When I click any of the buttons it shows all bus, tram and train data - how do I get them to just show one thing at a time and making sure that the other states are closed. I am really missing something here and need a pointer or two or three…
How can I add an ID to make each button open separate from each other and when one is clicked how can I close the rest of the divs - or open state, I am so lost here. Please help me out.
Cheers as always!
Here is a REPL of my code:
You need to have 3 different isHidden properties to control your divs. You can do it like this:
this.state = {
isHiddenBus: false,
isHiddenTrain: false,
isHiddenTram: false,
}
and then in your render like this:
{this.state.isHiddenBus && (
<div>
<h6>You can show Bus Data Now....</h6>
</div>
)}
{this.state.isHiddenTrain && (
<div>
<h6>You can show Train Data Now....</h6>
</div>
)}
{this.state.isHiddenTram && (
<div>
<h6>You can show Tram Data Now....</h6>
</div>
)}
also your buttons have to change to state accordingly to this.
busButton(){
console.log('Bus Button Was Pressed');
this.setState((prevState) => {
return{
isHiddenBus: !prevState.isHiddenBus
isHiddenTram: false
isHiddenTrain: false
};
});
}
trainButton(){
console.log('Train Button Was Pressed');
this.setState((prevState) => {
return{
isHiddenTrain: !prevState.isHiddenTrain
isHiddenBus: false
isHiddenTram: false
};
});
}
tramButton(){
console.log('Tram Button Was Pressed');
this.setState((prevState) => {
return{
isHiddenTram: !prevState.isHiddenTram
isHiddenTrain: false
isHiddenBus: false
};
});
}
you can do somthing like this:
import React, { Component } from 'react';
export class ModeExtended extends Component {
constructor() {
super();
this.state = {
curDivIndex:0,//currently visible div index
// isHidden: false,
}
}
renderDiv=()=>{
switch(this.state.curDivIndex){
case 1:return <div> <h6>You can show Bus Data Now....</h6> </div>
case 2:return <div> <h6>You can show Train Data Now....</h6> </div>
case 3:return <div> <h6>You can show Tram Data Now....</h6> </div>
}
return null
}
setVisibleDiv=(index)=>{
this.setState({curDivIndex:index})
}
render() {
return (
<div>
<h5>Mode Extended</h5>
<button onClick={()=>{this.setVisibleDiv(1)} }>Bus</button>
<button onClick={()=>{this.setVisibleDiv(2)}}>Train</button>
<button onClick={()=>{this.setVisibleDiv(3)}}>Tram</button>
{this.renderDiv()}
</div>
)
}
}
export default ModeExtended
EDIT
you want to have three different buttons, on click of each certain div
needs to be visible.
you can achieve this by maintaining the index of currently visible div.
when user clicks any button you have to set the index of div to be visible
which in the above code is achieved by using setVisibleDiv(index) call.
and you can at rendering time use curDivIndex to decide visible div.
Or you can achieve this by declaring state properties for all case:
this.state = {
hiddenBus: false,
hiddenTrain: false,
hiddenTram: false,
}
providing a name attribute to your buttons like so:
<button name="hiddenBus" onClick={toggleDisplay}>Bus</button>
<button name="hiddenTrain" onClick={toggleDisplay}>Train</button>
<button name="hiddenBus" onClick={toggleDisplay}>Tram</button>
then by defining the toggleDisplay function to toggle their display:
toggleDisplay = (event) => {
event.preventDefault(); // default behavior of a clicked button is to send a form so let's prevent this
const { name } = event.target; // find the clicked button name value
this.setState((prevState => ({
[name]: !prevState[name],
}));
}
Setting[name] enables us to target the state prop via the nameattribute value and update it based on the previous state.
Try this
import React, { Component } from "react";
export default class Create extends Component {
constructor(props) {
super(props);
this.state = {
currentBtn: null
};
}
clickedButton = e => {
this.setState({ currentBtn: e.target.id });
};
showDivElem = () => {
const { currentBtn } = this.state;
switch (currentBtn) {
case "A":
return <div>A</div>;
break;
case "B":
return <div>B</div>;
break;
case "C":
return <div>C</div>;
break;
default:
return <div>ABC</div>;
break;
}
};
render() {
console.log(this.state.currentBtn);
return (
<div>
<button id="A" onClick={e => this.clickedButton(e)}>
A
</button>
<button id="B" onClick={e => this.clickedButton(e)}>
B
</button>
<button id="C" onClick={e => this.clickedButton(e)}>
C
</button>
{this.showDivElem()}
</div>
);
}
}

React | Reusable dropdown component | how to get selected option?

Fairly new with react. I'm creating a dropdown button for a Gatsby project. The button toggle works, but I'm having trouble getting the selected value to the parent where I need it.
-Tried lifting the state up, but this resulted in the button not appearing at all. I was a bit confused here so maybe I was doing something wrong.
-Also tried using refs although I wasn't sure if this was the right use case, it worked, however it seems the value is grabbed before it's updated in the child component and I'm not sure how to change or work around this. (the code is currently set up for this)
Are either of these options right? or could anybody steer me in the right direction, thanks.
Dropdown in parent:
this.dropdownRef1 = React.createRef();
componentDidUpdate(){
console.log("Color Option:" + this.dropdownRef1.current.state.ColorOption)
}
<DropdownBtn ref={this.dropdownRef1} mainText="Color" options={this.props.pageContext.colors || ['']} />
DropdownBtn:
export default class refineBtn extends React.Component {
constructor(props) {
super(props);
}
state = {
open: false,
[this.props.mainText + "Option"]: "all",
};
dropdownBtnToggle = () => {
this.setState((prevState)=> {
return{open: !prevState.open};
});
};
optionClickHandler = (option) => {
this.setState(() => {
console.log(this.props.mainText + " updated to " + option)
return {[this.props.mainText + "Option"] : option}
});
};
render(){
const options = this.props.options
console.log("open: " + this.state.open)
return(
<div>
<button onClick={this.dropdownBtnToggle} >
{this.props.mainText}:
</button>
<div className={this.state.open ? 'option open' : "option"} >
<p key={"all"} onClick={() => this.optionClickHandler("all")}> all</p>
{options.map(option => (
<p key={option} onClick={() => this.optionClickHandler(option)}>{option}</p>
))}
</div>
</div>
);
}
}
You can respond to selection by allowing your component to accept a callback.
class MyComponent extends React.Component {
constructor(props) {
super(props)
this.state = {open: false, value: ''}
}
render() {
return (
<div>
<div onClick={() => this.setState({open: true})}>{this.state.value}</div>
<div style={{display: this.state.open ? 'block' : 'none'}}>
{this.props.options.map((option) => {
const handleClick = () => {
this.setState({open: false, value: option})
this.props.onChange(option)
}
return (
<div key={option} onClick={handleClick} className={this.state.value === option ? 'active' : undefined}>{option}</div>
)
})}
</div>
</div>
)
}
}
<MyComponent onChange={console.log} options={...}/>

react.js antd modal wrong behaviour

So I have this big messy component, I will try to slim it down, however keep most of it since I am unsure at this point what could be cause.
The issue is, that the game works as expected. When it is time for the modal to render, it appears at the bottom left of the page, with no styling floating left. The functionality however works as expected, the buttons work and it displays the raw content.
import { Modal } from 'antd';
//rest of imports
const initialState = {
visible: false,
streak: 0,
score: 0,
turn: 0,
previousPicks: [],
result: { result: "", player: "", computer: "" }
};
class Game extends React.Component {
constructor(props) {
super(props);
this.turnLimit = 10;
this.state = initialState;
}
componentWillUnmount() {
this.setState(initialState)
}
updateScore = () => {
//handles score
}
updatePreviousPicks = () => {
//update game data
}
onClickHandler = async (choice) => {
//fetching data from backend
self.showModal();
}
getAIResult = () => {
//
}
showModal = () => {
if (this.state.turn === 10) {
this.setState({
visible: true,
});
}
}
handleOk = () => {
this.setState(initialState)
}
handleCancel = () => {
this.setState(initialState)
}
render() {
return (
<div>
<div>
<Modal
title="Basic Modal"
centered={true}
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}></Modal>
</div>
<div className="container">
<div id="rockDiv" className={`choice`} onClick={() => this.onClickHandler("rock")}>
<Choices choice="rock"></Choices>
</div>
<div id="paperDiv" className={`choice`} onClick={() => this.onClickHandler("paper")}>
<Choices choice="paper"></Choices>
</div>
<div id="scissorsDiv" className={`choice`} onClick={() => this.onClickHandler("scissors")}>
<Choices choice="scissors"></Choices>
</div>
<Score score={this.state.score} bonus={this.state.streak} turn={this.state.turn} />
<div id="PlayerResult" className={this.state.result.result} >
{this.state.turn >= 1 ? <p>You</p> : <p></p>}
<Answer choice={`${this.state.result.player}`} />
</div>
<div id="AIResult" className={this.getAIResult()} >
{this.state.turn >= 1 ? <p>AI</p> : <p></p>}
<Answer choice={`${this.state.result.computer}`} />
</div>
</div>
</div>
)
}
}
export default Game
I have tried removing all CSS from the component, and still the modal does not show with the default antd design?
As I understand that current style you have doesn't like example of Antd.
Missing is you didn't import styles of Antd like this.
import { Modal, Button } from "antd";
import "antd/dist/antd.css";
Just need import style you will have what you need.
You can check my example here https://codesandbox.io/embed/8lr93mw8yj
<Modal
title="Basic Modal"
centered="true"
visible={this.state.visible}
onOk={this.handleOk}
onCancel={this.handleCancel}></Modal>
You do not need to wrap the "true" in brackets here as you are not calling a variable.

React Js custom accordion, open one item at the time

I have an accordion in React formed of a row component which is looped inside a body parent component. In the row I'm toggling the state showDetails to show/hide the details for each row, effectively opening the accordion item. But, since the state is for each row, how do I close one accordion item when I open another one?
Body:
export default class Body extends React.Component {
render() {
const {modelProps, showInfo, linkedRow} = this.props;
return (
<div className="c-table__body">
{this.props.model.map(
(subModel, i) =>
linkedRow ?
<LinkedRow
key={`${i}`}
model={subModel}
modelProps={modelProps}
/>
:
<Row
key={`${i}_${subModel.username}`}
model={subModel}
modelProps={modelProps}
showInfo={showInfo}
handleStatusChanged={this.props.handleStatusChanged}
/>
)}
</div>
);
}
}
Row:
class Row extends React.Component {
constructor(props) {
super(props);
this.state = {
userId: '',
showDetails: false,
showModal: false,
status: '',
value: '',
showInfo: false
};
render() {
const { model, modelProps, showInfo } = this.props;
return (
<div className="c-table__row">
<div className="c-table__row-wrapper">
{modelProps.map((p, i) => (
<div className={`c-table__item ${this.isStatusCell(model[p]) ? model[p] : p}`} key={i}>{this.isStatusCell(model[p]) ? this.toTitleCase(model[p]) : model[p]}</div>
))}
{showInfo ? (
<div className="c-table__item c-table__item-sm">
<a
name="view-user"
onClick={this.showDetailsPanel}
className={this.state.showDetails ? 'info showing' : 'info'}
>
<Icon yicon="Expand_Cross_30_by_30" />
</a>
</div>
) : (
''
)}
</div>
{this.state.showDetails ? (<ConnectedDetails user={model} statusToggle={this.handleStatusChange}/>) : null}
</div>
);
}
}
export default Row;
Not really sure how to approach this, maybe something in the body that check is there's any row open according to the showDetails state in the rows?
Thanks in advance
The approach is to lift the state of which <Row /> is open to the <Body /> component.
Also the method that switch between opened <Row /> is on the <Body /> component.
toggleOpen = (idx) => {
this.setState({ openRowIndex: idx });
}
then when you rendered your <Row />s you can pass a prop isOpen:
<Row
key={`${i}_${subModel.username}`}
model={subModel}
modelProps={modelProps}
showInfo={showInfo}
handleStatusChanged={this.props.handleStatusChanged}
isOpen={this.state.openRowIndex === i}
onToggle={_ => this.toggleOpen(i)}
/>

Categories

Resources