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

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.

Related

How to check one item in a list of checkboxes in react?

I have a list of items from API with 2 checkboxes for each item. one checkbox for approve and the other for decline. But I encountered 2 problems, all the checkboxes are checked using the checked attribute.
function AllReferral() {
const [status, setStatus] = React.useState(false)
const handleChange = (item, checked) => {
setStatus((prevState) => !prevState);
checked
? setChecked((prev) => [
...prev,
{
serviceName: item?.label,
status: status,
},
])
: setChecked((prev) => [...prev, item].filter((c) => c !== item));
};
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}
type="checkbox"
checked={status}
onChange={(e) => handleChange(item, e.target.checked)}
/>
</td>
<td>
<input
name={item?.name}
type="checkbox"
checked={!status}
onChange={(e) => handleChange(item, e.target.checked)}
/>
</td>
<td>{item?.label}</td>
</tr>
</tbody>
))}
</table>
</div>
)}
</div>
</section>
);
}
from above implementation, if I have 4 items, all 4 is checked by default. I want each item in the list to be checked separately either approve or decline. Secondly I want the setChecked to return an array of both approved and declined item differentiated by status true or false.

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},
...
}

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

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>
)

want to retrieve the value of specific row in which button was clicked. but i am getting the last one

I have table so I want to retrieve key/value of specific row in which button was clicked.
componentDidMount() {
let com = this;
firebase
.database()
.ref()
.child("bills")
.once("value", snap => {
let items = [];
snap.forEach(childD => {
items.push({
balance: childD.val().balance,
bill_num: childD.val().bill_num,
date: childD.val().date,
key: childD.val().key,
name: childD.val().name,
total: childD.val().total
});
});
Array.prototype.push.apply(com.state.products, items);
com.setState({
products: com.state.products
});
});
}
open = e => {
e.preventDefault();
console.log("kal" + this.state.value);
};
handleChange=event=>{
this.setState({value: event.target.value});
}
render() {
return (
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Bill number</th>
<th scope="col">Name</th>
<th scope="col">Date</th>
<th scope="col">Total</th>
<th scope="col">Balance</th>
<th scope="col">Delete</th>
<th scope="col">Open bill</th>
</tr>
</thead>
<tbody>
{console.log(this.state.products)}
{this.state.products.map((value, key) => (
<tr key={value.key}>
<th scope="row">{value.bill_num}</th>
<td>{value.name}</td>
<td>{value.date}</td>
<td>{value.total}</td>
<td>{value.balance}</td>
<td>
<form onSubmit={this.returnOrder}>
<input value={value.key} type="hidden" />
<button className="btn btn-danger" type="submit">
Return
</button>
</form>
</td>
<td>
<form onSubmit={this.open}>
<input value={value.key} onChange={this.handleChange} ref={ eKey => (this.inputeKey = eKey)} />
<button className="btn btn-info" type="submit">
Open
</button>
</form>
</td>
</tr>
))}
</tbody>
</table>
</div>
) : (
<Printout
keya={{
key: this.props.keyas
}}
/>
)}
);
}
}
Typically, tables in React are made from several components: whole table, row and for example buttons in row. So in table you place array of rows. Each row has it's child buttons. So you can send props to RowButtons child with information about clicked row.

Resources