Is there a way to stop the buttons activating the onClick? I've tried zIndexes, but they are not working.
return (
<div onClick={()=>history.push("/page")}>
<main className={classes.layout}>
<Paper className={classes.paperN}>
<div>
<h1> Examples </h1>
</div>
<div className={classes.theButtons}>
<Button> When I'm clicked, the onclick to new page occurs </Button>
</div>
</div>
</Paper>
</main>
</div>
);
There are two ways to do this.
One is to stop the propagation and/or default action of the button.
something like
<Button onClick={(e)=>{e.stopPropagation();e.preventDefault();}}> When I'm clicked, the onclick to new page occurs </Button>
the other is to detect if the click originated in a button and do nothing in your redirect handler.
<div
onClick={(e) => {
if (!e.target.closest("button")) {
history.push("/page");
}
}}
>
Related
I have two fields that show a modal when clicked on. I want to make one disabled if I select anyone first. I am using react-bootstrap for this project
<>
<div className='add-edit-product'>
<div className='d-flex align-items-center justify-content-center error-info mb-3'>
<img src={`../../../assets/img/about/${data.currencyHedge && data.marginFinancing ? "error-info-success.png" : "error-info.png"}`} className='me-3' />
{data.currencyHedge && data.marginFinancing ?
<p className='success'>Risks are acceptable due to mitigants</p> :
<p className='error'>The below risks require your attention</p>
}
</div>
<div className='form'>
<h2 className='mb-3'>Exchange rate risk</h2>
{data.currencyHedge && data.marginFinancing ? <p>No risk</p> :
<div>
{/*clicking on either of this tab will show a modal*/}
<div className='risk-tab' onClick={() => { setcurrencyHedgeModal(true); setSelected("currencyHedge") }}>
<h3>Enter a currency hedge</h3>
<img src={`../../../assets/img/about/${data.currencyHedge ? "correct-success.png" : "correct (1).png"}`} />
</div>
<div className='risk-tab' onClick={() => {setfinancingSufficientlyModal(true); setSelected("marginFinancing")}}>
<h3>Margin the financing sufficiently</h3>
<img src={`../../../assets/img/about/${data.marginFinancing ? "correct-success.png" : "correct (1).png"}`} />
</div>
</div>
}
</div>
</div>
<div className='footer_'>
<button onClick={() => hendelCancel()} className="footer_cancel_btn">cancel</button>
<button onClick={() => { nextStep() }} className='footer_next_btn'> Next</button>
</div>
{currencyHedgeModal && <CurrencyHedgeModal show={currencyHedgeModal} onHide={() => setcurrencyHedgeModal(false)} getModalData={(e) => modalGetData(e)} type={selected} />}
{financingSufficientlyModal && <FinancingSufficientlyModal show={financingSufficientlyModal} onHide={() => setfinancingSufficientlyModal(false)} getModalData={(e) => setData({ ...data, marginFinancing: e })} />}
</>
how can I add the logic to disable the next field if anyone is selected first. the image below is the form. (the green check mark shows when each form is filled and saved)
Question answer 1
Yes, if you want both inputs to trigger the opening of the modals you have to set onClick prop on both.
This depends on implementation and what do you specifically mean by disable an input. There are a couple of possible scenarios:
2.1 You may add a disabled class like so:
className={`${isOpened ? "disabled" : ""}`}
and then write some css.
2.2 You might rewrite onClick to just return when the modal is already opened instead of opening the second modal like so:
onClick={() => {
if (isOpened) return
setOpened(true)
}
P.S. You may need to add a second boolean flag to your state if you want this behaviour on both modals / inputs
Original answer
You have to use useState hook with a boolean flag isOpened
const [isOpened, setOpened] = useState(false)
Then update the state when clicking on yout input field
onClick={() => setOpened(true)}
Finally in your input fields you can use isOpened to disable them however you want, using styles or other logic.
P.S. Don't forget to call setOpened(false) when closig your modal
I am using react slick for making slides of poll. I am facing issue while clicking the poll option. Click gets fired after two clicks.
I think touch start is the issue here.
Not sure if it's like your code but the console logs the text when I click on the first image:
const ReactSlick = (props) => {
var settings = {
dots: true
};
return (
<div className="container">
<Slider {...settings}>
<div>
<img onClick={() => console.log("Clicked !")} src="http://placekitten.com/g/400/200" />
</div>
<div>
<img src="http://placekitten.com/g/400/200" />
</div>
</Slider>
</div>
);
}
```;
I'm getting trouble to understand the following situation in ReactJS.
I have a conditional rendering between two buttons: a button which shows another, basically. The second button is a submit type, and both buttons are inside the form. When I click at the first button to show/render the second one, in my understanding, it should just show the second button, and not submit the form automatically.
I reproduced the case with the create react app:
function App() {
const [showSubmit, setShowSubmit] = useState(false);
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<form method="POST" action="#">
{showSubmit ? (<button type="submit">Send</button>)
:
(<button type="button" onClick={() => setShowSubmit(true)}>
Show Submit
</button>)}
</form>
</header>
</div>
);
}
Why does the ReactJS automatically fires the submit event if I just want to show/render the submit button?
Posting here for anyone in the future who encounters this issue (probably me) - the issue you've described can be remedied by adding a key prop to the button elements, to let react distinguish between the button elements you're replacing.
Handle the form onSubmit function prevent the default function call, when ever you try to click on any button inside the form it will try to submit the form so use the e.preventDefault() to prevent it from submitting.
You can try handling the submission yourself using the onSubmit on the form tag instead of letting the browser do it for you.
import React, { useState } from 'react';
import './style.css';
function App() {
const [showSubmit, setShowSubmit] = useState(false);
console.log('state', showSubmit);
return (
<div className="App">
<header className="App-header">
<img src={'logo'} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<form method="POST" action="#" onSubmit={(e) => e.preventDefault()}>
{showSubmit ? (
<button type="submit">Send</button>
) : (
<button type="button" onClick={(e) => setShowSubmit(true)}>
Show Submit
</button>
)}
</form>
</header>
</div>
);
}
export default App;
I have a modal that when it is closed updates a state. The modal also has a div which will be replaced if a button is clicked. The button is replaced with a text area and 2 buttons (one of them a cancel.) If the cancel is clicked, the state updates and the text area hides. All good. However, if the user closes the modal, then the state is not updated and the div is shown next time.
I am unsure of how to set 2 states on close for the modal, I think this could sort this issue.
Code has been updated as per #jsNoob suggestion:
Hint component has
const [showModalProblemS_vid, setShowModalProblemS_vid] = useState(false);
<VideoModal showModal={showModalProblemS_vid} closeHandler={() => setShowModalProblemS_vid(false)} videoMessage={props.prob_s_vid} size='med'/>
So how to set a state which is not in the file is the issue
Modal Code below:
import Button from 'react-bootstrap/Button';
import Modal from 'react-bootstrap/Modal';
import { useState } from 'react';
function VideoModal({showModal = false, closeHandler = () =>{}, videoMessage, content, size}) {
const [confused, setConfused] = useState(false)
return (
<Modal
size={size}
show={showModal}
onHide={closeHandler}
onClose={()=> {setConfused(false); closeHandler()}}
backdrop="static"
keyboard={false}
>
<Modal.Body>
<video src={videoMessage} controls autoPlay></video>
<div>
{confused ? (
<div>
What have you found confusing about this video?
<textarea className='confusedText' rows="2"></textarea>
<Button className="confusedBtnSave">
Save
</Button>
<Button className="confusedBtnCancel" onClick={()=>setConfused(false)}>
Cancel
</Button>
</div>
) : (
<div>
<Button className="confusedBtn" onClick={()=>setConfused(true)}>
Confused?
</Button>
</div>
)}
</div>
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={closeHandler}>
Close
</Button>
</Modal.Footer>
</Modal>
)
}
export default VideoModal
Well to set multiple states you can do that inline
<Button onClick={() => {setState1(foo); setState2(bar)}}></Button
Or you could add them to a function and then call the function inline
function multipleStates(foo, bar){
setState1(foo)
setState2(bar)
}
<Button onClick={() => multipleState(foo, bar)}></Button>
I'm not sure if that is too broad of an answer for you, hopefully I haven't misinterpreted your question.
Got this working. I had to use the following:
onClick={() => {onClose(); setConfused(false)}}
note the semi-colon between the states
I have a reusable card component that allows me to render profile details in a gallery component. Clicking on any of the card redirects to the person's profile details using Link from react-router-dom. Now, I want to add delete icon on each card to allow the viewer to delete any of the profiles.
Understandably, clicking anything in the card redirects. Is there any way to avoid redirecting but just deleting the profile when the delete icon is clicked or any other workaround for this use case.
Here's the code snippet
const Card = ({ member, addTrash=false, removeFavorite }) => (
<Link to={`/profiles/${member.user_id}`} className="member__card">
<div className={`member__card__body ${className}`}>
<img src={member.photo} alt={member.user_name} />
{addTrash ? <span className="member__card__delete" onClick=
{removeFavorite}><i className="fa fa-trash"></i></span> : null}
</div>
<div className="member__card__footer">
<h3>{member.user_name}</h3>
<p>{member.age} • {member.location}</p>
</div>
</Link>
);
Help is most appreciated!
Thanks in advance
One way is by moving the icon to somewhere outside the react-router Link.
Eg.
const Card = ({ member, addTrash=false, removeFavorite }) => (
<div>
<Link to={`/profiles/${member.user_id}`} className="member__card">
<div className={`member__card__body ${className}`}>
<img src={member.photo} alt={member.user_name} />
</div>
<div className="member__card__footer">
<h3>{member.user_name}</h3>
<p>{member.age} • {member.location}</p>
</div>
</Link>
{addTrash ? <span className="member__card__delete" onClick=
{removeFavorite}><i className="fa fa-trash"></i></span> : null}
</div>
);
Also, being that you have a class member__card__body ${className} that wraps the card body, another way is by making only the image clickable, that is, enclosing the image with Link. That way the user can click on other parts of the card without being redirected.
Eg.
const Card = ({ member, addTrash=false, removeFavorite }) => (
<div>
<div className={`member__card__body ${className}`}>
<Link to={`/profiles/${member.user_id}`} className="member__card">
<img src={member.photo} alt={member.user_name} />
</Link>
{addTrash ? <span className="member__card__delete" onClick=
{removeFavorite}><i className="fa fa-trash"></i></span> : null}
</div>
<div className="member__card__footer">
<h3>{member.user_name}</h3>
<p>{member.age} • {member.location}</p>
</div>
</div>
);
I hope this helps?
As mentioned by #T Porter in the comments, your span code should be
{addTrash ? <span className="member__card__delete" onClick=
{(e)=>{removeFavorite();e.stopPropagation();}><i className="fa fa-trash"></i></span> : null}
I figured out that e.stopPropagation() didn't serve this use case. The fix was to call preventDefault() in the removeFavorite function.
removeFavorite = (id, e) => {
e.preventDefault() // This did the fix
this.props.deleteFavorite(id) // Delete the item
}
And for the Card component at the site of call
-------------
-------------
<Card member={{}} addTrash={true} removeFavorite={this.removeFavorite.bind(null, member.id}
Another thing I think you can do is to use css. You can add a class or an id to the delete button and give it a position of absolute and increase the z-index to make it sit right on top.