Apply a class to table row when checkbox is checked using states - reactjs

I have a simple table in parent component where I pass props to child in order to create rows. If the checkbox is checked I want to apply a style to the row and if its unchecked I want to remove it.All checked rows should have the styling. How can I implement this using react states system?
child component
...
render() {
return (
<tr>
<td>
<input className="action-check" type="checkbox"/>
</td>
<td>
<ButtonGroup />
</td>
<td>{this.props.name}</td>
<td>{this.props.date}</td>
</tr>
)
...

Try with hooks:
const [checked, setCheked] = useState(false)
return (
<tr className={"" + (checked ? "my-css-class" : "") }>
<td>
<input className="action-check" type="checkbox" onChange={(e)=> setCheked(e.target.checked)}/>
</td>
<td>
<ButtonGroup />
</td>
<td>{this.props.name}</td>
<td>{this.props.date}</td>
</tr>
)

Related

How to check an item and disable another checkbox in react?

I have a list of items from API. I also have two checkboxes to approve or decline an item. I want to be able to check the approve box and disable the decline box for an item.
function AllReferral() {
const [buttonStatus1, setButtonStatus1] = useState(false)
const [buttonStatus2, setButtonStatus2] = useState(false)
//function
const deactivateButton2 = () => setButtonStatus1(!buttonStatus1)
const deactivateButton1 = () => setButtonStatus2(!buttonStatus2)
return (
<section>
<div>
{user?.services?.length > 0 && (
<div>
<table>
<thead>
<tr>
<th >Approve</th>
<th >Decline</th>
<th >Service Name</th>
</tr>
</thead>
{user?.services?.map((item, index) => (
<tbody key={index}>
<tr>
<td>
<input
name={item?.name}
onClick={deactivateButton2}
type="checkbox"
value={checked}
onChange={(e) => setChecked(e.target.value)}
/>
</td>
<td>
<input
name={item?.name}
onClick={deactivateButton1}
type="checkbox"
value={checked2}
onChange={(e) => setChecked2(e.target.value)}
/>
</td>
<td>{item?.label}</td>
</tr>
</tbody>
))}
</table>
</div>
)}
</div>
</section>
);
}
Above is one of many trials I've done but I still don't get the desired action I need. I would appreciate some help
The easiest way to do this is to use a radio button. The default behavior of radio buttons is that if you select one radio button the others are automatically deselected.
If you want to have it as a checkbox, you can use a controlled input. Below is an example implementation that uses a shared state for the inputs.
function App () {
const [status, setStatus] = React.useState(false)
const handleChange = e => setStatus(prevState => !prevState)
return (
<div>
<label>
<input
type="checkbox"
checked={status}
onChange={handleChange}
/>
Accept
</label>
<label>
<input
type="checkbox"
checked={!status}
onChange={handleChange}
/>
Decline
</label>
</div>
)
}
ReactDOM.createRoot(document.getElementById("root")).render(<App />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
<div id="root"></div>

Reactjs Onchange input for function

I have a table with multiple inputs and want my second input on each row to change the number next to it with a formula of the first row: 5-DPS(from input). I want the number to change immediately after the DPS value changes.
Is there an easy-to-understand way for someone new to react?
This is my code:
import React, { useState, useEffect, useRef } from "react";
import "./index.css";
import Champions from "./components/Champions";
const Calculator = () => {
let DPS = React.createRef();
let TM = React.createRef();
let CCS = React.createRef();
let ME = React.createRef();
let UD = React.createRef();
const Burst = 5 - DPS;
const Sustain = 5 - TM;
const Hard = 5 - CCS;
const Reposition = 5 - ME;
const Offensive = 5 - UD;
//const [DPS, setDPS] = useState("");
return (
<table border={1} className="inlineTable" id="table2">
<tbody>
<tr>
<td />
<td>Pirmenybė</td>
<td>ŽPS</td>
<td>Staigus šaudymas</td>
</tr>
<tr>
<td>Žala</td>
<td>
<input type="number" id="DP" />
</td>
<td>
<input
type="number"
name="DPS"
id="DPS"
ref={DPS}
// onChange={(e) => setDPS(e.target.value)}
/>
</td>
<td>{Burst}</td>
</tr>
<tr>
<td />
<td>Pirmenybė</td>
<td>Sušvelninimas</td>
<td>Išlaikymas</td>
</tr>
<tr>
<td>Tvirtumas</td>
<td>
<input type="number" id="tP" />
</td>
<td>
{" "}
<input
type="number"
name="TM"
id="TM"
ref={TM}
//onChange={QuickChange.bind(this)}
/>
</td>
<td>Sustain</td>
</tr>
<tr>
<td />
<td>Pirmenybė</td>
<td>Minkštas</td>
<td>kietas</td>
</tr>
<tr>
<td>Minios valdymas</td>
<td>
<input type="number" id="CCP" />
</td>
<td>
<input
type="number"
name="CCS"
id="CCS"
ref={CCS}
// onChange={QuickChange.bind(this)}
/>
</td>
<td>Hard</td>
</tr>
<tr>
<td />
<td>Pirmenybė</td>
<td>Užvedimas</td>
<td>Perdėlioti</td>
</tr>
<tr>
<td>Mobilumas</td>
<td>
<input type="number" id="MP" />
</td>
<td>
<input
type="number"
name="ME"
id="ME"
ref={ME}
// onChange={QuickChange.bind(this)}
/>
</td>
<td>Reposition</td>
</tr>
<tr>
<td />
<td>Pirmenybė</td>
<td>Gynybinis</td>
<td>Agresyvus</td>
</tr>
<tr>
<td>Naudingumas</td>
<td>
<input type="number" id="UP" />
</td>
<td>
{" "}
<input
type="number"
name="UD"
id="UD"
ref={UD}
//onChange={QuickChange.bind(this)}
/>
</td>
<td>Offensive</td>
</tr>
</tbody>
</table>
);
};
export default Calculator;
You can show the value for the input with value of the state. When this value changes, it will be updated with the setDPS function.
const [DPS, setDPS] = useState(0);
<input
type="number"
name="DPS"
value={DPS}
onChange={(e) => setDPS(e.target.value)}
/>
If you want to depend this value and set other values, you can use a useEffect. When the value of DPS changes (inside the dependency array), the effect will run and update the value for the burst.
const [burst, setBurst] = useState();
useEffect(() => {
setBurst(5 - DPS)
}, [DPS])
Or you can set all values when DPS changes directly in the onChange
<input
type="number"
name="DPS"
value={DPS}
onChange={(e) => {
setDPS(e.target.value);
setBurst(5 - e.target.value);
}}
/>

Get input data from react.js table loop

I have to change some users point, so in loop how can i take that input value. Without hook
Use state! How can i declare many state. In loop ?
{this.state.data.map((user, index) => (
<tr key={user.id}>
<th scope="row" className="text-center">
{index + 1}
</th>
<td id="_lastname">{user.last_name}</td>
<td id="_firstname">{user.first_name}</td>
<td className="text-center">{user.category}</td>
<td className="text-center">
<input
type="text"
placeholder={user.point}
name="point"
/>
</td>
<td className="text-center">
<button
name="change"
value="true"
onClick={(e) => this.updateHandler(e)}
>
<i className="fas fa-check-circle">upd</i>
</button>
<button name="delete" value="true">
<i className="fas fa-times-circle">del</i>
</button>
</td>
</tr>
))}
Please note i just need that input value.
You want a dynamic input handler for you inputs.
You can have an state field for the input that is an object.
this.state = {
userPoints: {}
}
Then onChange handler to handle the dynamic inputs
handleDynamicInput = (id, event) => {
this.setState(prevState => ({
userPoints: [...prevState.userPoints, {[id]: event.target.value}]
}))
}
And your input should have the handler bind the user so you can update the state with the userid and userpoint.
<td className="text-center">
<input
value={this.state.userPoints[user.id] || ''}
onChange={this.handleChange.bind(this, user.id)}
type="text"
placeholder={user.point}
name="point"
/>
</td>
You userPoint state field should look like this
userPoints: {
...,
{userId: userPoint},
...
}

maintain single useState for all column values in a table row using react hooks

I have a react-bootstrap table which has 4 column values.
i am looking for a way using react hooks useState where - I can maintain state of all the column values in the same state object and whenever the state of any of the column values changes the entire row is updated.
I am very new to reactjs and react hooks, please do let me know if this can be done using any other react hook.
thanks!
In the below code..i have 2 useState..one to update state when the textarea is changed , other one to update the dropdown selected value.
I want to know if i can maintain single useState and everytime there is a change in any of the table columns i will trigger a single callback function and update state using single useState.
I also am not sure if the state will be replaced or the previous state(of all rows in the table) will be retained
<div>
<Table striped bordered hover>
<thead>
<tr>
<th>#</th>
<th>Text</th>
<th>Title</th>
<th>Data Property</th>
</tr>
</thead>
<tbody>
{data.map((item,index) => (
<tr key={index}>
<td>{item.id}</td>
<td>{item.color}</td>
<td>
<div className="userInput">
<InputGroup>
<Form.Control as="textarea" aria-label="With textarea" rows={1} value={newTitle.labelTitle} onChange={(e) => handleTitleChange(e)}/>
</InputGroup>
</div>
</td>
<td>
<Form.Group controlId="exampleForm.ControlSelect1">
<Form.Control as="select">
{dropDownData.map((data,index) => (
<option key={index} onChange = {(e)=>handleDataPropertyChange(e)}>{data}</option>
))}
</Form.Control>
</Form.Group>
</td>
</tr>
))}
</tbody>
</Table>
</div>
const [newTitle, setTitle] = useState(data);
const [newDataProperty, setDataProperty] = useState(dropDownData);
const handleTitleChange = (e) => {
setTitle(e.target.value);
}
const handleDataPropertyChange = (e) => {
setDataProperty(e.target.textContent);
}

How to reference other inputs in the same "row"?

onChange = ev => {
// how to get all inputs in this row?
};
render = () =>
<table className="MenuMenuOptionsWidget">
<thead>
<tr>
<th className="id">ID</th>
<th className="label">Label</th>
<th className="order">Order</th>
<th className="key">Key</th>
<th className="active">Active</th>
</tr>
</thead>
<tbody>
{this.state.options.map((opt,i) => <tr key={i}>
<td className="id">
{opt.id ? [<input type="hidden" name={`options[${i}][id]`} defaultValue={opt.id}/>,opt.id] : '*' }
</td>
<td className="label">
<input type="text" defaultValue={opt.label} name={`options[${i}][label]`} readOnly={!opt.active} onChange={this.onChange} />
</td>
<td className="order">
<input type="text" className="number" defaultValue={opt.order} name={`options[${i}][order]`} readOnly={!opt.active} onChange={this.onChange}/>
</td>
<td className="key">
<input type="text" defaultValue={opt.key} name={`options[${i}][key]`} readOnly={!opt.active} onChange={this.onChange}/>
</td>
<td className="active">
{opt.id ? <input type="checkbox" value="1" defaultChecked={opt.active} name={`options[${i}][active]`} onChange={this.onChange} /> : <a href="#" className="cr-delete-link" onClick={ev => this.onClickDelete(ev,i)}/>}
</td>
</tr>)}
</tbody>
</table>;
I've got a "loop" in my render() function which renders a bunch of inputs. I want to add the same onChange event to each of them. How can I access all the inputs in the row that caused the change event if I do this?
I can access the input that caused the change event via ev.target, but how do I get the others?
I could use jQuery: $(ev.target).closest('tr').find(...) but I'm looking for the idiomatic React way of doing it.
you want to make use of the ref property. by adding a unique ref to either the tr and calling children or a unique ref to each td, you can grab them when you need them.
<tr key={i} ref={`row${i}`}>
then grab the ref using refs
this.refs.row1.children
will grab all the td's within row1
You can use refs as a function. See here.
Try something like this: https://jsbin.com/kixowo/edit?js,console,output
var Component = React.createClass({
getInitialState() {
return {
options: [
'Row 1',
'Row 2'
]
};
},
rows: [],
onChange(row) {
this.rows[row].forEach((input) => {
// The values of all inputs in the row that changed
console.log(input.getDOMNode().value);
});
},
renderRows() {
this.rows = [];
return this.state.options.map((opt,i) => {
// Store and cache a new row and store inputs in the
// array using `refs` below.
this.rows.push([]);
return (<tr key={i}>
<td>{opt}</td>
<td>
<input ref={(input) => this.rows[i].push(input)} onChange={this.onChange.bind(this, i)} />
</td>
<td>
<input ref={(input) => this.rows[i].push(input)} onChange={this.onChange.bind(this, i)} />
</td>
</tr>);
});
},
render() {
return (
<table>
{this.renderRows()}
</table>
);
}
});
This way you can build up a dynamic set of inputs and call your on change event with the row number as an argument.

Resources