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);
}}
/>
Related
i am trying to implement auto complete feature in react JS.
it shows the autocomplete box, but shows [Object Object] for some reason, I have no idea why. I want it to show the email in the search box so as to implement autocomplete feature.
I would like to share my source code
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import './Home.css'
const SearchRepo = () => {
const [users, setUsers] = useState([]);
const [text, setText] = useState('');
const [suggestions, setSuggestions] = useState([]);
const onChangeHandler = (text) =>{
//setSeachUser(e.target.value);
let matches = []
if(text.length > 0){
matches = users.filter(user =>{
const regex = new RegExp(`${text}`,"gi");
return user.email.match(regex);
})
}
setSuggestions(matches);
setText(text);
}
useEffect(()=>{
const loadUsers = async()=>{
const response = await axios.get('https://reqres.in/api/users');
setUsers(response.data.data);
}
loadUsers();
},[])
return (
<div align="center">
<table border="0" width="100%" height="212px">
<tr>
<td bgcolor="#C0C0C0" height="55px"> <b>
<font face="Berlin Sans FB" color="#333333">Github Repo Search</font></b></td>
</tr>
<tr>
<td> </td>
</tr>
<tr>
<td>
<div align="center">
<table border="0" width="100%" className="SearchTable">
<div align="center">
<input type="text" placeholder=" Enter github repo ID / username" name="T1" size="88" value={text} onChange={e =>onChangeHandler(e.target.value)} className="inputArea" />
{suggestions && suggestions.map((suggestion,i)=>{
<div key={i}>{suggestion.email}</div>
})}
</div>
</table>
</div>
<div align="center">
<table border="0" width="100%" className="reposresultsTable">
<div align="left">
<tr>
<td bgcolor="#FFFFFF"> <b>
<font face="Verdana" size="2" className="labeltxt"><h3> Repos</h3></font></b>
</td>
</tr>
</div>
<div align="left">
<tr>
<td height="23"> <b>
<font face="Verdana" size="2">
<a href="https://test-restapi2.herokuapp.com/employees/">
mmmmmmmm</a></font></b></td>
</tr>
</div>
</table>
</div>
</td>
</tr>
</table>
</div>
);
}
export default SearchRepo;
why would it be showing that Object rather than the email? Please is there something i am not getting rightly?
Thanks guys, the issue was with a Curly brace. I have been able to resolve it. Thanks everyone.
Changing from this :
<div align="center">
<input type="text" placeholder=" Enter github repo ID / username" name="T1" size="88" value={text} onChange={e =>onChangeHandler(e.target.value)} className="inputArea" />
{suggestions && suggestions.map((suggestion,i)=>{
<div key={i}>{suggestion.email}</div>
})}
</div>
to this
<div align="center">
<input type="text" placeholder=" Enter github repo ID / username" name="T1" size="88" value={text} onChange={e =>onChangeHandler(e.target.value)} className="inputArea" />
{suggestions && suggestions.map((suggestion,i)=>
<div key={i}>{suggestion.email}</div>
)}
</div>
Ok. I am super lost here. I am attempting to return an a value from a nested array of objects. Here is what the database looks like.
Each object returns an array of staff as seen in this console log.
I cannot for the life of me display both names out of the array. I used the .flatMap() function to extract the data from the array, but when I go to render it in the component only the first name shows. Here is my codebase. Right now I am just console logging the data using .flatMap()
import React, { Fragment, useEffect } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import { Table } from 'react-bootstrap';
import Moment from 'react-moment';
import Button from '../components/Button';
import ActivitySummary from '../components/ActivitySummary';
import { projectsInfoDetails } from '../actions/projectInfoActions';
import { projectContacts } from '../actions/projectContactActions';
import { projectStaff } from '../actions/accountableStaffActions';
import SectionHeader from '../components/SectionHeader';
import Loader from '../components/Loader';
import Message from '../components/Message';
const ProjectScreen = ({ match }) => {
const dispatch = useDispatch();
const projectInfoDetails = useSelector(state => state.projectInfoDetails);
const { loading, error, projects } = projectInfoDetails;
const contactDetails = useSelector(state => state.projectContactDetails);
const { projectContact } = contactDetails;
const projectAccountableStaff = useSelector(state => state.projectStaff);
const { accountableProjectStaff } = projectAccountableStaff;
useEffect(() => {
dispatch(projectsInfoDetails(match.params.id));
dispatch(projectContacts(match.params.id));
dispatch(projectStaff(match.params.id));
}, [dispatch, match]);
const lastName = projectContact.map(l => l.contact.lastName);
const firstName = projectContact.map(f => f.contact.firstName);
const accountableStaffLastNames = accountableProjectStaff.flatMap(
({ accountableStaff }) => accountableStaff.map(data => data.lastName)
);
console.log(accountableStaffLastNames);
return (
<Fragment>
<div>
<SectionHeader sectionName='Project' />
<Button buttonName='Edit Project' />
</div>
{loading ? (
<Loader />
) : error ? (
<Message variant='danger'>{error}</Message>
) : (
<div style={{ backgroundColor: '#F8F8F8' }}>
<Table className='borderless'>
<tbody>
<tr>
<td>
<strong>Name: </strong>
{projects.name}
</td>
<td>
<strong>Status: </strong>
{projects.status}
</td>
</tr>
<tr>
<td>
<strong>State: </strong>
{projects.state}
</td>
<td>
<strong>County: </strong>
{projects.county}
</td>
</tr>
<tr>
<td>
<strong>Congressional District: </strong>
{projects.district}
</td>
<td>
<strong>Type: </strong>
{projects.type}
</td>
</tr>
<tr>
<td>
<strong>Funding Source: </strong>
<br />
{`${projects.fundingSource} ${projects.fundingSourceName}`}
</td>
<td>
<strong>Funding Source Goal: </strong>
<br />
{projects.fundingSourceGoal}
</td>
<td>
<strong>Start Date: </strong>
<br />
<Moment format='MM/DD/YYYY'>{projects.startDate}</Moment>
</td>
<td>
<strong>End Date: </strong>
<br />
{projects.endDate === null ? (
''
) : (
<Moment format='MM/DD/YYYY'>{projects.endDate}</Moment>
)}
</td>
<td>
<strong>Funding Percent: </strong>
<br />
{projects.fundingPercent}
</td>
</tr>
<tr>
<td>
<strong>Contact: </strong>
{firstName} {lastName}
</td>
</tr>
<tr>
<td>
<strong>Start Date: </strong>
<Moment format='MM/DD/YYYY'>
{projects.projectStartDate}
</Moment>
</td>
<td>
<strong>End Date: </strong>
{projects.projectEndDate === null ? (
''
) : (
<Moment format='MM/DD/YYYY'>
{projects.projectEndDate}
</Moment>
)}
</td>
</tr>
<tr>
<td colSpan='5'>
<strong>Goals and Objectives: </strong>
{projects.goalsAndObjectives}
</td>
</tr>
<tr>
<td colSpan='5'>
<strong>Success Description: </strong>
{projects.successDescription}
</td>
</tr>
<tr>
<td>
<strong>Accountable Staff: </strong>
</td>
</tr>
<tr>
<td>
<strong>Project ID: </strong>
{projects.projectId}
</td>
</tr>
</tbody>
</Table>
</div>
)}
<ActivitySummary />
</Fragment>
);
};
export default ProjectScreen;
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>
)
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.
<table>
<tr>
<td><input type="radio" name="groupName" value="song" ng-model="$parent.selectedSong"/></td>
<td>{{song.name}}</td>
<td>{{song.artist}}</td>
<td>{{song.genre}}</td>
<td>{{song.price}}</td>
<td>
<input type="button" value="Delete" ng-click="deleteItem(song.id)" />
</td>
<td>
<input type="button" value="View" ng-click="go('OneSong', song)" />
</td>
</tr>
</table>
<table border="1">
<tr><td id="Td1">Correct Table</td></tr>
<tr>
<td>Name: </td>
<td><input type="text" ng-model="editItem.name"/></td>
</tr>
<tr>
<td>Artist: </td>
<td><input type="text" ng-model="editItem.artist"/></td>
</tr>
<tr>
<td>Genre: </td>
<td><input type="text" ng-model="editItem.genre"/></td>
</tr>
<tr>
<td>Price: </td>
<td><input type="text" ng-model="editItem.price"/></td>
</tr>
<tr>
<td colspan="2">
<!--<input type="button" value="Insert "ng-click="addItem()"/>-->
Add New Song
<input type="button" value="Update" ng-click="updateItem()"/>
<input type="button" value="Cancel" ng-click="cancel()"/>
</td>
</tr>
</table>
From the little information you provided, I am taking a stab at this:
http://jsfiddle.net/V44fQ/
var app = angular.module('songApp',[]);
app.controller('SongCtrl',function($scope) {
$scope.edit_song = {};
$scope.song = [
{name:'Heartbreaker',artist:'Led Zeppelin',genre:'Rock',price:'.99'},
{name:'War Pigs',artist:'Black Sabbath',genre:'Rock',price:'.99'}
];
$scope.applySong = function(song) {
$scope.edit_song = angular.copy(song);
$scope.edit_song.song_index = $scope.song.indexOf(song);
};
$scope.saveSong = function() {
var idx = $scope.edit_song.song_index;
$scope.song[idx] = $scope.edit_song;
$scope.cancelSong();
};
$scope.cancelSong = function() {
$scope.edit_song = {};
};
});