My Delete API is http://localhost:8080/api/inventory/deleteproduct with the request body in JSON format:
{
"upc": "100101101111"
}
upc is the unique value for each product.
Here is my code for fetching data from API:
export function Inventory() {
const [product, setProduct] = useState(null);
useEffect(() => {
axios
.get("http://localhost:8080/api/inventory/products")
.then((response) => {
setProduct(response.data);
});
}, [url]);
if (product) {
return (
<div>
<h1>Inventory</h1>
<table className="table">
<thead>
<tr>
<th scope="col">Product Name</th>
<th scope="col">Brand</th>
<th scope="col">Category</th>
<th scope="col">Product Description</th>
<th scope="col">Price Per Unit</th>
<th scope="col">Available Stock</th>
<th scope="col">Reserved Stock</th>
<th scope="col">Shipped Stock</th>
<th scope="col">Image</th>
<th scope="col">Action</th>
</tr>
</thead>
<tbody>
{product.map((item) => (
<tr>
<td>{item.productName}</td>
<td>{item.brand}</td>
<td>{item.category}</td>
<td>{item.productDescription}</td>
<td>{item.pricePerUnit}</td>
<td>{item.availableStock}</td>
<td>{item.reservedStock}</td>
<td>{item.shippedStock}</td>
<td>
<img src={item.imageUrl} height={100} width={100} />
</td>
<td>
<Button>
onClick={() => {
onDeleteProduct();
}}
style={{ color: "red", marginLeft: 12 }}
/Button>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
}
I've already done the part of GET method to fetch all the data from API to the table.
Now I'm working on the DELETE method. I've also already created a delete button in each row. But I have no idea how to get the upc value in the row that I click the delete button to call an API http://localhost:8080/api/inventory/deleteproduct.
Can someone give me some idea, please?
Since each item has a unique upc, then your function should accept this as an argument
<td>
<Button>
onClick={() => {
onDeleteProduct(item.upc);
}}
style={{ color: "red", marginLeft: 12 }}
/Button>
</td>
and then your method would become like this
onDeleteProduct = itemUpc => {
axios.delete('http://localhost:8080/api/inventory/deleteproduct', { data: { upc: itemUpc }, headers: { } });
}
Related
This is my Table.js file code.
In this component i pass UserData which hold data that come from the server, handleEditButton method for update my data and handleDeleteButton for delete my data. When UserData is empty than i'm return "No data found" other wise it's show's data in tabular format
const Table = ({ UserData, handleEditButton, handleDeleteButton }) => {
if (UserData == '') {
return (
<>
{
<h2>N Data Found</h2>
}
</>
)
}
else {
return (
<>
{
<table cellSpacing={0} cellPadding={0} className={tableStyles.details}>
<thead>
<tr>
<th className={tableStyles.table}>Id</th>
<th className={tableStyles.table}>Name</th>
<th className={tableStyles.table}>Address</th>
<th className={tableStyles.table}>E-mail</th>
<th className={tableStyles.table}>Mobile No</th>
<th className={tableStyles.table}>Gender</th>
<th className={tableStyles.table}>City</th>
<th className={tableStyles.table}>Action</th>
</tr>
</thead>
<tbody>
{
(UserData && UserData.map((user) => (
<tr>
<th key={user.id}>{user.id}</th>
<td className={tableStyles.name}>{user.name}</td>
<td className={tableStyles.address}>{user.address}</td>
<td className={tableStyles.mail}>{user.mail}</td>
<td>{user.no}</td>
<td>{user.gender}</td>
<td>{user.city}</td>
<td colSpan={2} className={tableStyles.btnGroup}>
<button className={tableStyles.editBtn} onClick={(e) => { handleEditButton(user.id) }}>Edit</button>
<button className={tableStyles.deleteBtn} onClick={(e) => { handleDeleteButton(user.id) }}>Delete</button>
</td>
</tr>
)))
}
</tbody>
</table>
}
</>
)
}
}
You missed adding a ternary condition.
You can check with the following code.
const Table = ({ UserData, handleEditButton, handleDeleteButton }) => {
{
UserData == "" ? (
<h2>No Data Found</h2>
) : (
<table cellSpacing={0} cellPadding={0} className={tableStyles.details}>
<thead>
<tr>
<th className={tableStyles.table}>Id</th>
<th className={tableStyles.table}>Name</th>
<th className={tableStyles.table}>Address</th>
<th className={tableStyles.table}>E-mail</th>
<th className={tableStyles.table}>Mobile No</th>
<th className={tableStyles.table}>Gender</th>
<th className={tableStyles.table}>City</th>
<th className={tableStyles.table}>Action</th>
</tr>
</thead>
<tbody>
{UserData &&
UserData.map((user) => (
<tr>
<th key={user.id}>{user.id}</th>
<td className={tableStyles.name}>{user.name}</td>
<td className={tableStyles.address}>{user.address}</td>
<td className={tableStyles.mail}>{user.mail}</td>
<td>{user.no}</td>
<td>{user.gender}</td>
<td>{user.city}</td>
<td colSpan={2} className={tableStyles.btnGroup}>
<button
className={tableStyles.editBtn}
onClick={(e) => {
handleEditButton(user.id);
}}
>
Edit
</button>
<button
className={tableStyles.deleteBtn}
onClick={(e) => {
handleDeleteButton(user.id);
}}
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
);
}
};
I have a table that the user can edit the rows so i can save it into a state and save it inside a database but how can i get table row values and save it inside a state ? therefor the rows can be dynamic rows for example like grade i will fetch how many subjects inside a specific subject and the admin can put numbers inside rows so i can calculate how many grade does the user get for this subject
<table className="table-fill">
<thead>
<tr>
<th className="text-left">Subjects</th>
<th className="text-left">Grade</th>
</tr>
</thead>
<tbody className="table-hover">
<tr>
<td className="text-left" contentEditable="true">subject 1</td>
<td className="text-left" contentEditable="true">50</td>
</tr>
<tr>
<td className="text-left" contentEditable="true">subject 2</td>
<td className="text-left" contentEditable="true">40</td>
</tr>
<tr>
<td className="text-left" contentEditable="true">subject 3</td>
<td className="text-left" contentEditable="true">30</td>
</tr>
</tbody>
</table>
You should not use contentEditable="true" because it have no onChange event, so use input instead
import { useState } from "react";
export default function App() {
const [data, setData] = useState([
{ subject: "subject 1", grade: 50 },
{ subject: "subject 2", grade: 40 },
{ subject: "subject 3", grade: 30 }
]);
const onChangeRow = ({ type, index, value }) => {
const newData = data.map((item, idx) => {
if (idx === index)
return {
...item,
[type]: value
};
return item;
});
setData(newData);
};
const totalGrade = data.reduce((acc, cur) => {
acc += cur.grade;
return acc;
}, 0);
return (
<div className="App">
<table className="table-fill">
<thead>
<tr>
<th className="text-left">Subjects</th>
<th className="text-left">Grade</th>
</tr>
</thead>
<tbody className="table-hover">
{data.map((item, index) => (
<tr key={index}>
<td className="text-left">
<input
type="text"
defaultValue={item.subject}
onChange={(e) =>
onChangeRow({
type: "subject",
index,
value: e.target.value
})
}
/>
</td>
<td className="text-left">
<input
type="number"
defaultValue={item.grade}
onChange={(e) =>
onChangeRow({
type: "grade",
index,
value: parseInt(e.target.value || 0)
})
}
/>
</td>
</tr>
))}
</tbody>
</table>
<div>Total grade: {totalGrade}</div>
</div>
);
}
style.css
input {
border: none;
outline: none;
}
You can check in my codesandbox. Hope it help!
const SheetTable = ({ sheets }) => {
return (
<table className="sheetTableComponent">
<thead>
<tr>
<td>No</td>
<td>track</td>
<td>item</td>
</tr>
</thead>
<tbody>
{sheets.map((item, index) => (
<tr key={index}>
<td>{index}</td>
<td>
<div>{item.code}</div>
</td>
<td>
<div>{item.item}</div>
</td>
</tr>
))}
</tbody>
</table>
)
}
This is my table. After populate it got about 10 rows. I want if one row click, it will highlight, the other rows un-highlight
Hope it will solve your problem.
Are you looking for something like this?
changeColor = (id) => {
this.setState({ selected: id });
};
render() {
const { selected, arr } = this.state;
return (
<table className="sheetTableComponent">
<thead>
<tr>
<td>No</td>
<td>track</td>
<td>item</td>
</tr>
</thead>
<tbody>
{arr.map((item, index) => (
<tr
key={index}
style={{
color: selected === item.id ? "red" : ""
}}
onClick={() => this.changeColor(item.id)}
>
<td>{index}</td>
<td>
<div>{item.code}</div>
</td>
<td>
<div>{item.item}</div>
</td>
</tr>
))}
</tbody>
</table>
);
}
Live working demo
Couple of ways to do it, but most simple is to just use css
Assign tabindex to your rows and use :focus selector to highlight the row
<tr key={index} className="row" tabindex="0">
CSS:
.row:focus {
outline: none;
background: green;
}
I'm working on a project in NextJS and I found an interesting problem for which I can't seem to find a solution -
I have an array of objects I've acquired from the Civic GAPI. In this array, most the objects are general election contests, but some are also referendums. The contest and referendum objects have different structures.
Here's a general election contest object:
14:
candidates: (2) [{…}, {…}]
district: {name: "Thurston County", scope: "countywide", id: "ocd-division/country:us/state:wa/county:thurston"}
level: ["administrativeArea2"]
office: "Commissioner District 3"
roles: ["legislatorUpperBody"]
sources: [{…}]
type: "General"
__proto__: Object
And here's a referendum object:
15:
district: {name: "Washington", scope: "statewide", id: "ocd-division/country:us/state:wa"}
referendumTitle: "Advisory Vote No. 8 (Senate Bill 6505)"
referendumUrl: "https://wei.sos.wa.gov/agency/osos/en/press_and_research/PreviousElections/2014/General-Election/Pages/Online-Voters-Guide.aspx"
sources: [{…}]
type: "Referendum"
__proto__: Object
Here's my page that renders this data (I've included the entire page, but obviously you can skip the conditionals for loading the data from GAPI):
import useSWR from 'swr';
const Contests = (props) => {
const url = '/api/voterInfo';
const fetcher = (url) => fetch(url).then((r) => r.json());
const { data, error } = useSWR(url, fetcher);
if (error)
return (
<div className='alert alert-danger' role='alert'>
<span className='sr-only'>Failed to load data!</span>
</div>
);
if (!data)
return (
<div
className='spinner-border spinner-border-lg text-danger'
role='status'
style={{ margin: '10rem', width: '20rem', height: '20rem' }}
></div>
);
if (data && data !== null) {
const { contests } = data.data;
return (
<div>
<table className='table table-hover'>
<caption>List of contests in your area</caption>
<thead style={{ fontFamily: 'Righteous, sans-serif' }}>
<tr>
<th scope='col'>#</th>
<th scope='col'>Dist ID</th>
<th scope='col'>Dist Name</th>
<th scope='col'>Dist Scope</th>
<th scope='col'>Office</th>
<th scope='col'>Type</th>
</tr>
</thead>
<tbody>
{contests.map((contest, idx) => (
<tr key={idx}>
<th scope={idx}>{idx + 1}</th>
<td>{contest.district.id}</td>
<td>{contest.district.name}</td>
<td>{contest.district.scope}</td>
<td>{contest.office}</td>
<td>{contest.type}</td>
</tr>
))}
</tbody>
</table>
{console.log(contests[0].level[0])}
</div>
);
}
};
export default Contests;
If I only render the first level of key-value pairs, it's easy to see how the difference in contest and referendum objects causes one or the other to miss values:
Because I've set the map to render the keys from contests it misses the referendum values for keys referendumTitle and referendumUrl.
What's the best way to go about dealing with this? I came up with two possible solutions I'm not sure how to implement:
Is there a conditional I could set to only map contests, and have a separate page to map referendums? How would I separate them (before/while/after) mapping an array?
OR
Is there a way to dynamically map the values of the keys regardless of their identifier?
Any other ideas?
Is there a way to dynamically map the values of the keys regardless of their identifier?
You could use Object.keys:
Object.keys(contest).map(key => console.log(key))
I ended up splitting the API's returned data into 3 categories with if statements, and then making a component to load each one separately, because they benefited from being formatted differently
But here's the initial page I created to debug the returned data. It separates the data but displays it all on one page, with conditional rendering based on what objects were returned:
import Link from 'next/link';
import useSWR from 'swr';
const Contests = (props) => {
const url = '/api/voterInfo';
const fetcher = (url) => fetch(url).then((r) => r.json());
const { data, error } = useSWR(url, fetcher);
if (error)
return (
<div className='alert alert-danger' role='alert'>
<span className='sr-only'>Failed to load data!</span>
</div>
);
if (!data)
return (
<div
className='spinner-border spinner-border-lg text-danger'
role='status'
style={{ margin: '10rem', width: '20rem', height: '20rem' }}
></div>
);
if (data && data !== null) {
const { contests } = data.data;
const primaryElections = [];
const generalElections = [];
const referendums = [];
contests.map((contest) => {
if (contest.type === 'Referendum') {
referendums.push(contest);
} else if (contest.type === 'General') {
generalElections.push(contest);
} else if (contest.type === 'Primary') {
primaryElections.push(contest);
}
});
console.log(primaryElections, generalElections, referendums);
return (
<div>
<table className='table table-hover'>
<caption>List of contests in your area</caption>
{primaryElections.length > 0 && (
<>
<thead style={{ fontFamily: 'Righteous, sans-serif' }}>
<tr>
<th scope='col' style={{ width: '10px' }}>
#
</th>
<th scope='col'>Type</th>
<th scope='col'>Office</th>
<th scope='col'>Dist Name</th>
<th scope='col'>Dist ID</th>
<th scope='col'>Dist Scope</th>
</tr>
</thead>
<tbody>
{primaryElections.map((election, idx) => (
<tr key={idx}>
<td style={{ width: '10px' }}>{idx + 1}</td>
<td>{election.type}</td>
<td>{election.office}</td>
<td>{election.district.name}</td>
<td>{election.district.scope}</td>
<td>{election.district.id}</td>
</tr>
))}
</tbody>
</>
)}
{generalElections.length > 0 && (
<>
<thead style={{ fontFamily: 'Righteous, sans-serif' }}>
<tr>
<th scope='col' style={{ width: '10px' }}>
#
</th>
<th scope='col'>Type</th>
<th scope='col'>Office</th>
<th scope='col'>Dist Name</th>
<th scope='col'>Dist ID</th>
<th scope='col'>Dist Scope</th>
</tr>
</thead>
<tbody>
{generalElections.map((election, idx) => (
<tr key={idx}>
<td style={{ width: '10px' }}>{idx + 1}</td>
<td>{election.type}</td>
<td>{election.office}</td>
<td>{election.district.name}</td>
<td>{election.district.scope}</td>
<td>{election.district.id}</td>
</tr>
))}
</tbody>
</>
)}
{referendums.length > 0 && (
<>
<thead style={{ fontFamily: 'Righteous, sans-serif' }}>
<tr>
<th scope='col' style={{ width: '10px' }}>
#
</th>
<th scope='col'>Type</th>
<th scope='col'>Title</th>
<th scope='col'>Subtitle</th>
<th scope='col'>Language</th>
<th scope='col'>District</th>
<th scope='col'>Scope</th>
<th scope='col'>Open Civic Data ID</th>
</tr>
</thead>
<tbody>
{referendums.map((referendum, idx) => (
<tr key={idx}>
<td style={{ width: '10px' }}>{idx + 1}</td>
<td>{referendum.type}</td>
<td>{referendum.referendumTitle}</td>
<td>{referendum.referendumSubtitle}</td>
<td>
<Link href={`${referendum.referendumUrl}`}>
<a>{referendum.referendumUrl}</a>
</Link>
</td>
<td>{referendum.district.name}</td>
<td>{referendum.district.scope}</td>
<td>{referendum.district.id}</td>
</tr>
))}
</tbody>
</>
)}
</table>
</div>
);
}
};
export default Contests;
Can anyone suggest me good modal popup for reactjs and ? I want it for delete confirmation. I tried react-foundation-apps 's modal, but due to less documentation i am unable to use it for delete functionality in tabular data.
var React = require('react');
var EmployeeList = React.createClass({
render: function() {
var employees = this.props.employees.map(function(e, i){
return (
<tr key={i}>
<td>{e.employeeName}</td>
<td><a title="edit" href="#"><i className="fi-pencil"></i></a></td>
<td>
<a title="delete" href="#"><i className="fi-trash"></i></a>
</td>
</tr>
)
}, this);
return (
<div>
<table id="users">
<thead>
<tr>
<th>Employee</th>
<th>Edit</th>
<th>Delete</th>
</tr>
</thead>
<tbody>
{employees}
</tbody>
</table>
</div>
);
}
});
module.exports = EmployeeList;
Plus
Suggest me good datatable/datagrid for reactjs with foundation.
A model is a simple pattern you can build yourself. The main attributes are absolute positioning, show/hide and high zIndex. Here is an example.
import React from 'react';
import Actions from '../../flux/Actions';
import TreeViewB from './../common/jTreeViewB';
let JumpListSty = {
backgroundColor: '#e1ded5',
left: '20px',
maxHeight: '80%',
overflow: 'auto',
position: 'absolute',
top: '30px',
width: '350px',
zIndex: '100'
};
export default class JumpList extends React.Component {
clickHandler = (node) => { Actions.selectJumpNode(node); Actions.appActions('jump'); }
render() {
if (this.props.hide) return null;
let options = {
icon: {sun: 1, leaf: 2, snow: 3},
typeName: ['node', 'nodeLevel']
};
let isMobile = (this.props.appState.deviceType == 'mobile');
return (
<div id='JumpListSty' style={JumpListSty}>
<TreeViewB data={this.props.data} options={options} titleClick={this.clickHandler} mobile={isMobile} />
</div>
);
}
}
<JumpList data={jumpData} appState={this.props.appState} hide={hideJump} />
A datagrid is a simple pattern also. It is a arrangement of columns contained in a map of rows. You can use an html table or not.
function dataMap(item, index) {
return (
<tr key={item._id + index}>
<td ></td>
<td style={columnSty}>{item.userinclude}</td>
<td style={columnSty}>{item.domaininclude}</td>
<td style={columnSty}>{item.userexclude}</td>
<td style={columnSty}>{item.domainexclude}</td>
<td style={columnSty}>{item.userskip}</td>
<td style={columnSty}>{item.domainskip}</td>
<td style={lastColumnSty}>{item._id}</td>
</tr>
)
}
export default class AggregateList extends React.Component {
render() {
let list = this.props.data.map(dataMap);
return (
<div id='AggregateListSty' style={AggregateListSty}>
<table >
<thead>
<tr>
<th ></th>
<th style={columnHeaderSty}></th>
<th style={columnHeaderSty}>Protested</th>
<th style={columnHeaderSty}></th>
<th style={columnHeaderSty}>Excluded</th>
<th style={columnHeaderSty}></th>
<th style={columnHeaderSty}>Skipped</th>
<th style={lastColumnSty}></th>
</tr>
<tr>
<th ></th>
<th style={columnHeaderSty}>User</th>
<th style={columnHeaderSty}>All</th>
<th style={columnHeaderSty}>User</th>
<th style={columnHeaderSty}>All</th>
<th style={columnHeaderSty}>User</th>
<th style={columnHeaderSty}>All</th>
<th style={lastColumnSty}></th>
</tr>
</thead>
<tbody>
{list}
</tbody>
</table>
</div>
);
}
}