How to show particular table row detail when it is clicked (Reusable Component) in react - javascript

I have created a reusable table component but am facing an issue showing detail for the particular row. what I was doing is if the row id is equal to a particular row id then I was trying to show the detail, but in my case for all rows details are visible.
Codesandbox : reusableTableComponent
what I tried:
const TableCustm = ({ TableHeader, dataVal, selectedRowDetail }) => {
const [selectedTableRow, setSelectedTableRow] = useState(null);
console.log("selectedRowDetail", selectedRowDetail);
console.log("selectedTableRow", selectedTableRow);
const data = dataVal.map((row) => {
const rowData = [];
const keys = Object.keys(row);
keys.forEach((key, index) => {
if (index !== 0) {
rowData.push({
key: TableHeader[index],
val: row[key]
});
}
});
return (
<>
<tr onClick={() => setSelectedTableRow(row)}>
{rowData.map((i) => (
<td className="font-lato text-[14px] text-p_black font-semibold py-0">
<div className="d-flex py-2">{i.val}</div>
</td>
))}
</tr>
// **********************detail table Row ********************
<tr>
<td colspan={TableHeader.length}>
<div style={{ background: "#dcdcdc", padding: "20px" }}>
<button className="btn btn-primary">clickme</button>
<hr className="my-2" />
<div className="d-flex ">row detail</div>
</div>
</td>
</tr>
// *******************end detail
</>
);
});
return (
<Table responsive borderless>
<thead>
<tr>
{TableHeader.map((item) => (
<th key={item.id} className="font-normal">
<div className="flex py-[15px]">{item.label}</div>
</th>
))}
</tr>
</thead>
<tbody className="border-0">{data}</tbody>
</Table>
);
};

I can see what you're trying to do. I'm by no means a react specialist, but nothing on Netflix was gripping me, so took up your challenge.
You're almost there, just a few things that are happening that are getting in your way.
I've got this working on codesandbox: https://codesandbox.io/embed/goofy-tereshkova-66p1ki?fontsize=14&hidenavigation=1&theme=dark
1) React is re-rendering the App Component when you click on the row
I'm not sure the best way to get around this, but every time you click the row (even with my step 2), it will re-generate the UUID. I got around this by just hard coding the IDs, as I assume you'll have a better way for generating IDs (or will need to figure out a way to stop the reloading.
But, for now, hardcode the id so you can follow step 2
const testData = [
{
id: 1,
2) Your use of useState between the Parent (App) and Child (TableCustm) components.
Not sure if this is intentional, but you're duplicating selectedTableRow state in both components. What I think you should do is hold the state in the parent (App) component, but pass both the state and the setState method to the child component inside of app.js like so:
<TableCustm
TableHeader={TableHeader}
dataVal={dataValue}
selectedRowDetail={selectedRow}
setRow={setSelectedRow}
/>
So now, inside the child component (TableCustom.js) you can set the state of the selected row like so:
<tr
onClick={(i) => {
setRow(row.id);
}}
>
And then, becaue you're also passing down (from the Parent to Child component) the current selected row selectedRowDetail, you can then conditionally render the row on the screen.
{row.id === selectedRowDetail &&
<tr>
<td colspan={TableHeader.length}>
<div style={{ background: "#dcdcdc", padding: "20px" }}>
<button className="btn btn-primary">clickme</button>
<hr className="my-2" />
<div className="d-flex ">row detail</div>
</div>
</td>
</tr>
}
Also, you might want to add a conditional step when setting the state of the selected row to null, so when you click again it disappears:
<tr
onClick={(i) => {
if (row.id === selectedRowDetail) {
setRow(null);
} else {
setRow(row.id);
}
}}
>
Hope that helps!

When you are working with React you have to understand when to use state and when to use props.
In your scenario you have two approaches:
When you want to show many details at same time, each row manage it owns state.
When you want to show one detail at a time, you must likely want to the parent Table component to manage your state.
It seems you want the approach 2) show one detail at a time, so you have to show it based on the selected row with selectedTableRow === row:
import React, { useState } from "react";
import { Table } from "react-bootstrap";
const TableCustm = ({ TableHeader, dataVal, selectedRowDetail }) => {
const [selectedTableRow, setSelectedTableRow] = useState(null);
console.log("selectedRowDetail", selectedRowDetail);
console.log("selectedTableRow", selectedTableRow);
const data = dataVal.map((row) => {
const rowData = [];
const keys = Object.keys(row);
keys.forEach((key, index) => {
if (index !== 0) {
rowData.push({
key: TableHeader[index],
val: row[key]
});
}
});
return (
<>
<tr
onClick={() =>
setSelectedTableRow(selectedTableRow === row ? null : row)
}
>
{rowData.map((i) => (
<td className="font-lato text-[14px] text-p_black font-semibold py-0">
<div className="d-flex py-2">{i.val}</div>
</td>
))}
</tr>
{selectedTableRow === row && (
<tr>
<td colspan={TableHeader.length}>
<div style={{ background: "#dcdcdc", padding: "20px" }}>
<button className="btn btn-primary">clickme</button>
<hr className="my-2" />
<div className="d-flex ">row detail</div>
</div>
</td>
</tr>
)}
</>
);
});
return (
<Table responsive borderless>
<thead>
<tr>
{TableHeader.map((item) => (
<th key={item.id} className="font-normal">
<div className="flex py-[15px]">{item.label}</div>
</th>
))}
</tr>
</thead>
<tbody className="border-0">{data} </tbody>
</Table>
);
};
export default TableCustm;
CodeSandbox: https://codesandbox.io/s/epic-mcnulty-g0hqhw?file=/src/TableCustm.js
PS: I believe your code need refactoring and I highly recommend you the Code With Mosh videos to start working with React: https://www.youtube.com/watch?v=Ke90Tje7VS0
Refactored code (not ideal yet, but better):
import React, { useState } from "react";
import { Table } from "react-bootstrap";
const TableRow = ({ data, onClickRow, showDetails }) => {
return (
<>
<tr onClick={onClickRow}>
{data.map((item, i) => (
<td
key={i}
className="font-lato text-[14px] text-p_black font-semibold py-0"
>
<div className="d-flex py-2">{item.val}</div>
</td>
))}
</tr>
{showDetails && (
<tr>
<td colSpan={data.length}>
<div style={{ background: "#dcdcdc", padding: "20px" }}>
<button className="btn btn-primary">clickme</button>
<hr className="my-2" />
<div className="d-flex ">row detail</div>
</div>
</td>
</tr>
)}
</>
);
};
const TableCustm2 = ({ TableHeader, dataVal }) => {
const [selectedTableRow, setSelectedTableRow] = useState(null);
return (
<Table responsive borderless>
<thead>
<tr>
{TableHeader.map((item) => (
<th key={item.id} className="font-normal">
<div className="flex py-[15px]">{item.label}</div>
</th>
))}
</tr>
</thead>
<tbody className="border-0">
{dataVal.map((row, index) => (
<TableRow
key={index}
data={TableHeader.map((key) => ({
key: key.label,
val: row[key.label]
}))}
onClickRow={() => {
setSelectedTableRow(index);
}}
showDetails={selectedTableRow === index}
/>
))}
</tbody>
</Table>
);
};
export default TableCustm2;

Related

document.location.pathname updating when routing from class component to functional component in react-router

These are the routes:
const routes = [
{ url: "", component: Home }, //class
{ url: "doctors", component: Doctors }, //class
{ url: "activedevices", component: ActiveDevices }, //functional
{ url: "nurses", component: Nurse }, //functional
{ url: "patients", component: PatientTable }, //functional
{ url: "floor-management", component: FloorManagement }, //class
{ url: "organizations", component: Organizations }, //functional
]
<Switch>
{routes.map((data, i) => (
<Route
key={i}
exact
path={`/${data.url}`}
component={data.component}
/>
))}
<Route path="*" component={()=> <Redirect to='/' />} />
</Switch>
I'm using window.location.pathname to determine the current path and highlight the corresponding menu item.
Dashboard
Patients
Floor Management
It is working fine when I try to navigate between class to class component or class to functional component. But when I try functional to functional component, the window.document.pathname does not update which results in respective menu item not being highlighted and last one remain highlighed. But the routing still works, I'm routed to the clicked routes and it also shows updated route in the address bar but not inside the script.
These are images showing updates routes in address bar but not in pathname:
Nurses
Active Devices
Here is the code for a functional component:
import React, { useState, useRef, useEffect } from "react";
import { Table, Pagination, Badge, Dropdown } from "react-bootstrap";
import { Link } from "react-router-dom";
import ActiveDevicesRow from "./ActiveDeviceRow";
import {baseURL, API, BEARER_TOKEN} from '../../../config'
const ActiveDevices = () => {
const [activeDevices, setActiveDevices] = useState(null)
let serial=1;
var myHeaders = new Headers();
myHeaders.append("Authorization", BEARER_TOKEN);
var requestOptions = {
method: 'GET',
headers: myHeaders,
redirect: 'follow'
};
async function getActiveDevices(){
await fetch(baseURL+API.DEVICES, requestOptions)
.then(res => res.json())
.then(res => {
if(Array.isArray(res)) setActiveDevices(res)
})
.catch(err => console.log(err))
// console.log(activeDevices)
}
useEffect(()=>{
getActiveDevices()
}, [])
const [data, setData] = useState(
document.querySelectorAll("#ActiveDevices_basic_table tbody tr")
);
const sort = 5;
const activePag = useRef(0);
const [test, settest] = useState(0);
// Active data
const chageData = (frist, sec) => {
for (var i = 0; i < data.length; ++i) {
if (i >= frist && i < sec) {
data[i].classList.remove("d-none");
} else {
data[i].classList.add("d-none");
}
}
};
// use effect
useEffect(() => {
setData(document.querySelectorAll("#ActiveDevices_basic_table tbody tr"));
}, [test]);
// Active pagginarion
activePag.current === 0 && chageData(0, sort);
// paggination
let paggination = Array(Math.ceil(data.length / sort))
.fill()
.map((_, i) => i + 1);
// Active paggination & chage data
const onClick = (i) => {
activePag.current = i;
chageData(activePag.current * sort, (activePag.current + 1) * sort);
settest(i);
};
// console.log(document.querySelectorAll(".sorting_1 input")[0].checked);
return (
<div className="col-12">
<div className="card">
<div className="card-header">
<h4 className="card-title">Active Devices</h4>
</div>
<div className="card-body">
<Table responsive className="w-100">
<div
id="ActiveDevices_basic_table"
className="dataTables_wrapper"
>
<table
id="example5"
className="display dataTable no-footer w-100"
style={{ minWidth: 845 }}
role="grid"
aria-describedby="example5_info"
>
<thead>
<tr role="row">
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Patient ID: activate to sort column ascending"
style={{ width: 73 }}
>
S.R. No.
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Date Check in: activate to sort column ascending"
style={{ width: 100 }}
>
ID
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Patient Name: activate to sort column ascending"
style={{ width: 100 }}
>
Name
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Doctor Assgined: activate to sort column ascending"
style={{ width: 120 }}
>
Serial
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Disease: activate to sort column ascending"
style={{ width: 62 }}
>
DeviceType
</th>
<th
className="sorting"
tabIndex={0}
aria-controls="example5"
rowSpan={1}
colSpan={1}
aria-label="Action: activate to sort column ascending"
style={{ width: 47 }}
>
State
</th>
</tr>
</thead>
<tbody>
{activeDevices && activeDevices.length !== 0 ? activeDevices.map((device, index)=>
<ActiveDevicesRow
key={'device'+device.id}
srNo={serial++}
id={device.id}
serial={device.serial}
name={device.name}
deviceStatus={device.isActive}
deviceType={device.deviceType}
onClick=""
/>
)
: <tr><td colSpan='7' style={{textAlign:'center'}}>No Data Available</td></tr>
}
</tbody>
</table>
<div className="d-flex justify-content-between align-items-center mt-3">
<div className="dataTables_info">
Showing {activePag.current * sort + 1} to{" "}
{data.length > (activePag.current + 1) * sort
? (activePag.current + 1) * sort
: data.length}{" "}
of {data.length} entries
</div>
<div
className="dataTables_paginate paging_simple_numbers"
id="example5_paginate"
>
<Link
className="paginate_button previous disabled"
to="#"
onClick={() =>
activePag.current > 0 &&
onClick(activePag.current - 1)
}
>
Previous
</Link>
<span>
{paggination.map((number, i) => (
<Link
key={i}
to="#"
className={`paginate_button ${
activePag.current === i ? "current" : ""
} ${i > 0 ? "ml-1" : ""}`}
onClick={() => onClick(i)}
>
{number}
</Link>
))}
</span>
<Link
className="paginate_button next"
to="#"
onClick={() =>
activePag.current + 1 < paggination.length &&
onClick(activePag.current + 1)
}
>
Next
</Link>
</div>
</div>
</div>
</Table>
</div>
</div>
</div>
);
};
export default ActiveDevices;
And here is the code for a class component:
import React, { Component } from "react";
import { Dropdown } from "react-bootstrap";
import { Link } from "react-router-dom";
import DoctorsAccordion from "./DoctorsAccordion";
class Doctors extends Component {
componentDidMount(){
document.title = "Active Doctors"
}
render() {
return (
<React.Fragment>
<div className="form-head d-flex mb-3 mb-lg-5 align-items-start">
<Link onClick={this.onClick} className="btn btn-danger">
+ New Doctor
</Link>
<div className="input-group search-area ml-auto d-inline-flex">
<input type="text" className="form-control" placeholder="Search here" />
<div className="input-group-append">
<span className="input-group-text c-pointer">
<i className="flaticon-381-search-2"></i>
</span>
</div>
</div>
<Dropdown className="ml-3">
<Dropdown.Toggle variant="outline-primary" id="dropdown-basic">
<i className="flaticon-381-controls-3 "></i> Filter
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-menu-right">
<Dropdown.Item href="#">A To Z List</Dropdown.Item>
<Dropdown.Item href="#">Z To A List</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<Dropdown className="ml-3">
<Dropdown.Toggle variant="outline-primary" id="dropdown-basic">
Newest
</Dropdown.Toggle>
<Dropdown.Menu className="dropdown-menu-right">
<Dropdown.Item href="#">Newest</Dropdown.Item>
<Dropdown.Item href="#">Old</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<Link onClick={this.onClick} className="btn btn-outline-primary ml-3">
<i className="flaticon-381-menu-1 mr-0"></i>
</Link>
</div>
<DoctorsAccordion />
</React.Fragment>
);
}
}
export default Doctors;
Here is a screenshot showing functional compoenent path being updated in address bar but no getting logged on console:
Screenshot of functional comp path not logged
why can't you use `
props.location.pathnameinsted of
window.location.pathname
to determine the current path and refer this link Read the current full URL with React?

React onClick taking an extra click to change state

I have a function that is used to setState in my App.js script. I have passed this as props to my FilteringTable.js component which calls this function when a table row is clicked.
It always takes an extra click to change the state.
How do I fix this problem? Please help
App.js
class App extends React.Component{
state={
data:[]
}
setStateData = rowData =>{
this.setState({
data:rowData
})
};
render(){
return (
<Router>
<div className='App'>
<Header data={this.state.data}/>
<Switch>
<Route path="/filtertable" render={(props)=> <FilteringTable{...props}setStateData={rowData => this.setStateData(rowData)}/>}/>
</Switch>
<Footer data={this.state.data}/>
</div>
</Router>
)
}
}
export default App
FilteringTable.js
export const FilteringTable = (props) => {
return (
<>
<div className="content">
<table className="list-table"
{...getTableProps()}
onClick={()=> {props.setStateData(selectedFlatRows);
console.log("Clicked",selectedFlatRows)}}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps()}>
{column.render('Header')}
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{page.map(row => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>
{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
</div>
</>
)
}
The onClick function in the table component is where the function to setState is used. And it takes an extra click to change the state.
Thank you in advance!!
Try moving this call to useEffect:
useEffect(()=> {props.setStateData(selectedFlatRows)},[selectedFlatRows])

Rendering multiple componets in a table react

I have a component that renders a table with data from a database, I am experiencing a problem where I cant render the second component called EditButton bottom of the code, I managed to render the 1st component DeleteButton bottom of the code, but when I try to render another button I get errors. The goal is to render another button in the table. Thanks in advance :)
import React, { useState } from 'react';
import { Button } from 'semantic-ui-react';
import { currentloginid } from '../login/loginid.js';
import { deletequestion } from '../question/deletequestion.js';
import { editanswer } from '../answer/editanswer.js';
export const ViewQuestionComponent = () => {
let [state, setState] = useState([]);
const handleViewQuestion = async () => {
try {
const response = await fetch('http://localhost/gotaquestion/api/api.php?action=viewquestion', {
method: 'GET',
credentials: 'include'
});
const data = await response.json();
const result = await data;
setState(data);
} catch (e) {
console.log(e);
}
}
return (
<div>
<ViewQuestion onClick={handleViewQuestion} />
<div id="questions">
<Table rows={state}>
<DeleteButton onClick={deletequestion} />
</Table>
</div>
</div>
);
};
export function ViewQuestion({onClick}) {
return (
<Button onClick={onClick}>View Question</Button>
);
}
export default ViewQuestion;
const Table = ({ rows, setIdTobeDeleted, children }) => (
<table className="ui single line table">
<tbody>
{rows.map((row) => (
<tr key={row.questionid}>
<td>{row.question}</td>
<td>{row.timestamp}</td>
<td>{row.catagories}</td>
<td>{row.answer === null ? "Not Answered" : row.answer}</td>
<td>
{React.cloneElement(children, { questionid: row.questionid })}
</td>
<td>
//I want the EditButton to render there instead on DeleteButton
{React.cloneElement(children, { questionid: row.questionid })}
</td>
<td>{row.questionid}</td>
</tr>
))}
</tbody>
</table>
);
const EditButton = ({ questionid, onClick }) => (
<button
className="ui negative basic button"
onClick={() => onClick(editanswer)}
>Edit Question</button>
);
const DeleteButton = ({ questionid, onClick }) => (
<button
className="ui negative basic button"
onClick={() => onClick(questionid)}
>Delete Question</button>
);
I think in your view you have missed the edit button.
Please consider changing
return (
<div>
<ViewQuestion onClick={handleViewQuestion} />
<div id="questions">
<Table rows={state}>
<DeleteButton onClick={deletequestion} />
</Table>
</div>
</div>
);
to
return (
<div>
<ViewQuestion onClick={handleViewQuestion} />
<div id="questions">
<Table rows={state}>
<DeleteButton onClick={deletequestion} />
</Table>
<Table rows={state}>
<EditButton onClick={editanswer} />
</Table>
</div>
</div>
);

How to pass data from a table row and pass it to another component when it renders?

I have a component that shows a table and one of its columns have a field Actions which has buttons (view, edit, delete etc.). On button click, I need to render another component (component is a popup) and pass the data from the table so that it displays the data in some form which I need to further add.
I have managed to get the current data from its row by passing in onClick. I tried to use state for another component to render but it didn't work out. I'm using Semantic-UI React components to display the button with animations.
Here is the code that has the table,
const MainContent = () => {
const [actions, setActions] = useState(false);
const handleView = (rowData) => {
console.log(rowData);
setActions(true);
if (actions == true) return <ParentView />;
};
....
....
const contents = (item, index) => {
return item.routeChildEntry ? (
<>
<tr key={index}>
<td>{item.appName}</td>
<td></td>
<td>{item.createdTs}</td>
<td>{item.pattern}</td>
<td></td>
<td></td>
<td></td>
<td>
<Button animated onClick={() => handleView(item)}>
<Button.Content visible>View</Button.Content>
<Button.Content hidden>
<Icon name="eye" />
</Button.Content>
</Button>
</td>
</tr>
{item.routeChildEntry.map(routeContents)}
</>
) : (
....
....
....
);
};
return (
<div>
....
{loading ? (
<div className="table-responsive">
<table className="table">
<thead>
<tr>
<th>AppName</th>
<th>Parent_App</th>
<th>Created_Date</th>
<th>Req_Path</th>
<th>Resp_Code</th>
<th>Resp_Content_Type</th>
<th>Resp_Delay</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{data.map((routes, index) => {
return routes.map(contents, index);
})}
</tbody>
</table>
</div>
) : (
....
....
)}
</form>
</div>
</div>
</div>
</div>
</div>
</div>
);
};
export default MainContent;
Below is the component to render on button click,
import React from "react";
import Popup from "reactjs-popup";
import { Icon } from "semantic-ui-react";
const Parent = (props) => {
return (
<Popup trigger={<Icon link name="eye" />} modal closeOnDocumentClick>
<h4>in parent</h4>
</Popup>
);
};
export default Parent;
How can I render the other component and pass data to it on button click?
Data can be passed to other components as props.
For example, if your component is <ParentView />, and the data you are passing is contained in the variable rowData, you can pass it as:
<ParentView dataPassedByAkhil = {rowData}/>
Then in your ParentView component,
export default function ParentView({dataPassedByAkhil}) {
console.log(dataPassedByAkhil);
Alternatively, you can accept the data as props as below
export default function ParentView(props) {
console.log(props.dataPassedByAkhil);
If you want to open and close another popup, you can pass a state just like above.
<PopupComponent open={stateSetForPopupByParent}/>
Example of popup using state.
Updated link above with how to pass data to the dialog from rows of buttons
Here is the full code:
export default function FormDialog() {
const [open, setOpen] = React.useState(false);
const [valueofRow, setValueOfRow] = React.useState();
const handleClickOpen = (value) => {
setValueOfRow(value);
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button
variant="outlined"
color="primary"
onClick={() => {
handleClickOpen("John");
}}
>
Row 1 - value is John
</Button>
<br />
<br />
<Button
variant="outlined"
color="primary"
onClick={() => {
handleClickOpen("Sally");
}}
>
Row 2 Value is Sally
</Button>
<Dialog
open={open}
onClose={handleClose}
aria-labelledby="edit-apartment"
>
<DialogTitle id="edit-apartment">Edit</DialogTitle>
<DialogContent>
<DialogContentText>Dialog fired using state</DialogContentText>
<h1>{valueofRow} was clicked and passed from the row</h1>
<TextField
autoFocus
margin="dense"
id="field"
label="some field"
type="text"
fullWidth
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose} color="secondary">
Cancel
</Button>
<Button onClick={handleClose} color="primary">
Submit
</Button>
</DialogActions>
</Dialog>
</div>
);
}

How do I pass props from child to parent in React?

I have a dynamic table that renders a list of items that the user selects. The user can select an item from a drop down menu and then add that item to the list. As of right now I store the item list in the state of my component, which allows the table to render dynamically. What I would like is for the user to be able to click on an item in the table and be able to edit certain parts of that item, such as the quantity that they are selecting. Once the user clicks on that item from the table a Modal will appear that gets filled with the information from that specific item. My problem is that within the modal, when the user changes say the quantity of that item, I would like the Modal to close and then update the table with that value that the user changed.
Is there a way to pass this updated list of items back to the parent? Or is this not viable? and if so, what would be the right way to go about this. I will post my code below so that you guys can get a better understanding about what I'm trying to accomplish.
NOTE My modal isn't complete but I just would like to know how I can pass props back to the parent component.
Parent.js
export default Parent extends React.Component{
constructor(props){
super(props);
this.state = {
ItemList = [],
IDClicked = "",
}
AddItemHandler(){
...stuff to add to ItemList
}
RenderModal(){
let itemList = this.state.ItemList
<ItemModal items={itemList} />
}
RowClick(e){
//console.log(e.target.id)
var items = this.state.ItemList;
for(let i = 0; i < items.length; i++){
if(items[i].ID == e.target.id){
var Item = {
ID: items[i].ID,
PartName: items[i].PartName,
Quantity: items[i].Quantity
}
}
}
//console.log("Item clicked: " + JSON.stringify(Item));
this.setState({IDClicked: e.target.id})
(document.getElementById('myModal')).style.display = "block";
}
RenderTable(items){
var rows = [];
for(let i = 0; i < items.length; i++){
rows.push(
<tr style={{backgroundColor: '#B7BCDF'}} id={items[i].ID} key={i}>
<td style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
{items[i].PartName}
</td>
<td style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
{items[i].Description}
</td>
<td style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
{items[i].Type}
</td>
<td style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
{items[i].Quantity}
</td>
<td style={{maxWidth: '20px', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap'}} onClick={this.RowClick.bind(this)} id={items[i].ID}>
{items[i].Units}
</td>
</tr>
)
}
return (
<div className="TableScroll2" style={{width: '99.5%', height: 'none'}}>
<table className="TableRows">
<tbody>
{rows}
</tbody>
</table>
</div>
);
}
render(){
return(
<div id="mymodal">
this.RenderModal();
</div>
<div style={{width: '50%', marginLeft: 'auto', marginRight: 'auto'}}>
<div className="ParTableContainer" style={{marginTop: '5%'}}>
<table className="PartTableHeaderContainer" style={{textAlign: 'center'}}>
<thead>
<tr>
<th style={{width: '20%'}}>Part Name</th>
<th style={{width: '20%'}}>Description</th>
<th style={{width: '20%'}}>Type</th>
<th style={{width: '20%'}}>QTY</th>
<th style={{width: '20%'}}>U/M</th>
</tr>
</thead>
</table>
</div>
{this.RenderTable(this.state.ItemList)}
</div>
<button style={{marginTop: '2%', marginBottom: '5%'}} onClick={this.AddItemHandler.bind(this)}>Add Item</button>
}
}
You cannot pass props from a child to the parent. There are however ways for a child to communicate with it's parent, which could be used to solve your problem.
The way to go is usually to use callbacks - pass a function from your parent to your child which the child can call to update the state of the parent. Here is an example that updates the parent state:
function Parent() {
const [counter, setCounter] = useState(0)
return (
<div>
Current: {state}
<Child increment={() => {
setCounter(current => current + 1)
}}}/>
</div>
)
}
function Child(props) {
return <button onClick={props.increment}>Click me</button>
}
(This example was done using hooks, which I strongly recommend learning)
Here it is without hooks:
class Parent extends Component {
constructor() {
this.state = { counter: 0 }
}
render() {
return (
<Child increment={() => {
this.setState((current) => {
return { counter: current.counter + 1 }
})
}}}/>
)
}
}
function Child(props) {
return <button onClick={props.increment}>Click me</button>
}

Categories