How to disable second form if first one is clicked - reactjs

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

Related

set first box clicked as a default at the first load

Im new in reactjs and I create a list of card by mapping in reactjs but I want my first card be clicked as a default at the first load what can i do for this code.
<div className="d-flex">
{data && data.length > 0
? data.map((item, index) => {
return (
<>
<div className="box-stock" onClick={() => selectData(item)}>
<div className="top-stock skewed p-5">
<h1>{item.symbol}</h1>
<strong className="text-center">
<span> (0.25)</span>
{item.stockNum}
</strong>
<Label className="text-center">
EPS:<span className="text-white">{item.EPS}</span>
</Label>
<Label className="text-center">
P/E:<span className="text-white">{item.PE}</span>
</Label>
</div>
</div>
</>
);
})
: 'no data'}
</div>
You can use useEffect hook to run program once it renders. Here, in useEffect pass empty array as a dependency so, that it runs only once.
useEffect(() => {
selectData(data[0])
}, [])
You can add click event on first load using javascript. The button will trigger the event on first load and you will get your first card clicked. Here is the code:
document.getElementsByClassName("box-stock").click()

Is there a way to add a class to all elements that has a property set to true?

I have an object with a property of questions. questions is an array of 13 objects.Each object has a choices array that have between 2-4 objects and each object has an isCorrect property that is either true or null.
All my questions are being rendered. I have a button that I want to add a classname to each correct answer that the user selected. Do you guys have any suggestions of how I can achieve this?
{quiz.questions.map((question, index) => (
<ContentWrapper key={question._key}>
<h3>
{`${index + 1}. `}
{question.title}
</h3>
{question.choices.map(choice => (
<ChoiceStyle id={"wrapper" + choice._key} key={choice._key}>
<input
type="radio"
id={choice._key}
name={question._key}
onChange={updateScore}
value={choice.isCorrect === null ? "0" : "1"}
/>
<label htmlFor={choice._key}>{choice.title}</label>
</ChoiceStyle>
))}
<ButtonComponent
type="button"
buttonType="second"
title="Sjekk svar"
onClick={() => {
calculateScore();
}}
/>
That button just calculates the score but I might need to add another function to that button? I am also using styled components
You have multiple approaches to do this, the easiest and less invasive way is to add a ternary condition to show/hide the class name based on an isCorrect property.
I'm assuming that quiz is a state that is changed in each onChange to refresh all the real-time changes on the quiz. At this point:
{quiz.questions.map((question, index) => (
<ContentWrapper key={question._key}>
<h3>
{`${index + 1}. `}
{question.title}
</h3>
{question.choices.map(choice => (
<ChoiceStyle id={"wrapper" + choice._key} key={choice._key}>
<input
type="radio"
id={choice._key}
name={question._key}
onChange={updateScore}
className={`${choice.isCorrect ? 'is-valid':''}`}
value={choice.isCorrect === null ? "0" : "1"}
/>
<label htmlFor={choice._key}>{choice.title}</label>
</ChoiceStyle>
))}
<ButtonComponent
type="button"
buttonType="second"
title="Sjekk svar"
onClick={() => {
calculateScore();
}}
/>
The trick is the following ternary condition:
className={`${choice.isCorrect ? 'is-valid':''}`}
The problem that occurs is that the class gets applied right away. I
don't want the correct answer to show up unless the user has clicked
the button component
Then you will need to add a new property to your choice object to check and play with it. Let's assume something like:
const choice={
key: "some key"
isCorrect: true
/// other fields
}
// more code
{quiz.questions.map((question, index) => (
<ContentWrapper key={question._key}>
<h3>
{`${index + 1}. `}
{question.title}
</h3>
{question.choices.map(choice => (
<ChoiceStyle id={"wrapper" + choice._key} key={choice._key}>
<input
type="radio"
id={choice._key}
name={question._key}
onChange={updateScore}
className={`${choice.isValid ? 'is-valid':'' }`}
value={choice.isSelected === null ? "0" : "1"}
/>
<label htmlFor={choice._key}>{choice.title}</label>
</ChoiceStyle>
))}
<ButtonComponent
type="button"
buttonType="second"
title="Sjekk svar"
onClick={() => {
calculateScore();
}}
/>
In each updateScore, you'll need to check if the choice is correct and matches your business logic and add the new property (isValid) to trigger it.
const updateScore =()=>{
// some unknown logic
// some validations and then:
choice.isValid = true,
}
Since (I've assumed) that you are setting the quiz in React's state, the new property will force a refresh of the state, applying the class name in the user clicks.

Why does my table component filter crash the browser tab?

I have a page with a table which is working quite fine and is very performant as it should be. I'm now trying to implement a filter for it so the users can easily check only what they need. But one weird thing is happening. If I have the filter component commented out, everything works fine. If I include it in the component it should be, the browser becomes extremely slow and even crashes my chrome tab. I was trying to comment out all the code in that component to check where the problem is but I can't figure it out.
My weird component code without the comments:
import { Grid, LuxButton } from 'luxclusif-material';
import React, { useState } from 'react';
import { FilterComponentStyles } from './FilterComponent.styles';
export default function FilterComponent() {
const classes = FilterComponentStyles();
const [status, setStatus] = useState('Supplier');
return (
<>
<div className={classes.spacing}>
{/* commented out stuff */}
</div>
<div className={`${classes.statusMenu} ${classes.spacing}`}>
<Grid
container
direction="row"
justify="flex-start"
alignItems="center"
className={classes.heightStatus}>
<div className={classes.rightMargin}>
<LuxButton
variant="contained"
luxColor={(status === 'Supplier' ? 'secondary' : 'default')}
onClick={() => setStatus('Supplier')}
className={classes.transformTextNone}
disableElevation>
<span className={classes.addButtonText}>Supplier</span>
</LuxButton>
</div>
<div className={classes.rightMargin}>
<LuxButton
variant="contained"
luxColor={(status === 'Active' ? 'secondary' : 'default')}
onClick={() => setStatus('Active')}
className={classes.transformTextNone}
disableElevation>
<span className={classes.addButtonText}>Active</span>
</LuxButton>
</div>
<div className={classes.rightMargin}>
<LuxButton
variant="contained"
luxColor={(status === 'Inactive' ? 'secondary' : 'default')}
onClick={() => setStatus('Inactive')}
className={classes.transformTextNone}
disableElevation>
<span className={classes.addButtonText}>Inactive</span>
</LuxButton>
</div>
</Grid>
</div>
</>
);
}
This FilterComponent is being called like this:
<TableContainer component={Paper} >
<FilterComponent ></FilterComponent>
<Table>
{/* table code */}
</Table>
</TableContainer>
Notes: LuxButton is an extension of material-ui Button and its luxColor property is the extension to the color property.

React toggle button based on API return

I am currently working on a React application.
As you can see in the following code, there are two buttons. I would like to show the grey button if the user hasn't created a Request (default). If the user has created a Request the button should be green.
Problem:
The main issue is, that the map function (API) no returning any value for "no Requests" so I am not able to identify "no Requests". That means that .isEmpty,.length, .indexOf,... and also the "if-else" is not working because there is nothing to validate.
const greenButton = (
<Button color="green" onClick={e => DeleteRequest(e, rest.id)}>Request</Button>
);
const greyButton = (
<Button color="grey" onClick={e => CreateRequest(e, props.reservationID)}>Request</Button>
);
return (
<div>
{greyButton}
{requests.map((rest, i) => (
<div key={i}>
{rest.requester === username
? <div>{greenButton}{rest.requester} <i
aria-hidden="true"
className="delete icon"
onClick={e => DeleteRequest(e, rest.id)} />
</div> : <div />}
</div>
))}
</div>
);
Result in the UI:
API:
Any Ideas? (If you need more information, I am happy to provide more details)
conditional rendering
Use a ternary on requests being a defined/truthy object and has a truthy length property. In the true branch map the requests, grey button in false branch. This covers requests being either initially (or returned from the API) undefined or an empty array [].
return (
<div>
{requests && requests.length ? requests.map((rest, i) => (
<div key={i}>
{rest.requester === username
? <div>{greenButton}{rest.requester} <i
aria-hidden="true"
className="delete icon"
onClick={e => DeleteRequest(e, rest.id)} />
</div> : <div />}
</div>
)) : (
{greyButton}
)}
</div>
);

Navigate with tabIndex when elements where hidden

Summary
I want to understand how the tabulation navigation works on browser, in order to perform custom input with suggestion field on React.
Objective
The objective is to provide 2 custom input to the use with suggestion dropdown. When I click to my input, the dropdown shows correctly and I can navigate through the tabulation key to my suggestions. But when I try to navigate to the next input, the dropdown shows but I can't navigate through my second dropdown suggestion.
Code example
I have the following JSX code:
class InputDropdown React.Component {
render() {
return(<div>
<div id="input1" className="input-wrapper" onMouseEnter={...} onMouseLeave={...} onBlur={...}>
<input className={"input"}
value={this.state.search_input}
onKeyDown={(e) => e.keyCode==13?this.props.validate(this.state.search_input)}
onFocus={this.setState(display_dropdown_input1: true)}
/>
<div className={"dropdown-wrapper" + this.state.display_dropdown_input1?"":"hidden"}>
{this.props.suggestion.map((suggestion, index) =>
<div className="suggestion"
tabIndex={0}
onKeyDown={(e) => e.keyCode==13?this.props.validate(suggestion.text)}
onBlur={index+1==this.props.suggestion.length?this.setState({display_dropdown_input1:false})}
>{suggestion.text}</div>)}
</div>
</div>
<div id="input2" className="input-wrapper" onMouseEnter={...} onMouseLeave={...} onBlur={...}>
<input className={"input"}
value={this.state.search_input}
onKeyDown={(e) => e.keyCode==13?this.props.validate(this.state.search_input)}
onFocus={this.setState(display_dropdown_input2: true)}
/>
<div className={"dropdown-wrapper" + this.state.display_dropdown_input2?"":"hidden"}>
{this.props.suggestion.map((suggestion, index) =>
<div className="suggestion"
tabIndex={0}
onKeyDown={(e) => e.keyCode==13?this.props.validate(suggestion.text)}
onBlur={index+1==this.props.suggestion.length?this.setState({display_dropdown_input2:false})}
>{suggestion.text}</div>)}
</div>
</div>
</div>)
}
}
Question
It's as if the tabulation navigations road is prepared on the first tabulation pressed and if element appear after this press they are not taken in count.
Is it possible to perform it in React?

Resources