react table sort not working on calculated column - javascript

my "calculated" column Header: 'EV/Resource ($ per oz)' when sorting does not appear to sort in any ascending or descending order when pressed in the react table, it randomize the table sort in a way. Am i doing a "calculated column" correctly ? all my other columns sort correctly.
{
Header: 'in-situ ($b)',
accessor: 'minerals_value',
Cell: (row) => {
return (row.value / 100 / 1000000000).toFixed(2)
},
},
{
Header: 'GMV ($/t)',
accessor: 'minerals_value_per_ton',
},
{
Header: 'EV/Resource ($ per oz)',
id: 'evresource',
accessor: 'evresource',
sortType: 'basic',
Cell: (row) => {
return Number(
row.row.original.company.enterprise_value /
100 /
row.row.original.primary_mineral.contained
).toFixed()
},
},
table render:
<table {...getTableProps()}>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th {...column.getHeaderProps(column.getSortByToggleProps())}>
{column.render('Header')}
<span>{column.isSorted ? (column.isSortedDesc ? ' ▼' : ' ▲') : ''}</span>
</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map((cell) => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>

You need to implement a custom accessor in order for the sorting to work correctly.
Specifically:
{
Header: 'EV/Resource ($ per oz)',
id: 'evresource',
accessor: customAccessor,
and
function customAccessor(row) {
return Number(
row.company.enterprise_value /
100 /
row.primary_mineral.contained
)
}
}

Related

How to input array into 1 column table

How to input array into 1 column table ? Audience number 2 have 2 Films B & C. I want to become 1 column. ex [Film B, Film C] in Column Film.
My Table =>
The Table Image
const AudienceListComponent = () => {
const [audience, setAudience] = useState([])
console.log("audience", audience)
const getAllAudience = () => {
AudienceService.getAllAudiences().then((response) => {
console.log('response', response)
setAudience(response.data)
})
}
useEffect(() => {
getAllAudience()
}, [])
return (
<div>
<table className="table table-bordered table-bordered">
<thead className="table-dark">
<tr>
<th>No</th>
<th>Audience Name</th>
<th>Film</th>
</tr>
</thead>
<tbody>
{
audience.map((aud, i) => (
<tr key={aud.id}>
<td>{i + 1}</td>
<td>{aud.name}</td>
{aud.film.map(films =>
<td>{films.title}</td>
)}
</tr>
))
}
</tbody>
</table>
</div>
);
};
export default AudienceListComponent;
Solved by #Hamza Khan in a comment:
You need to run the map loop inside your td element like this: <td> {aud.film.map(films => films.title )} </td>

I want to sort my entire react table on the basis of one column value

export const COLUMNS = [
{
Header : 'Total Cases',
accessor : 'totalcases',
},
{
Header : 'Active Cases',
accessor : 'activecases',
},
{
Header : 'Total Recovery',
accessor : 'recovery',
},
{
Header : 'Total Death',
accessor : 'deaths',
},
{
Header : 'New Cases',
accessor : 'newcases',
},
]
function Table({countryData}) {
const columns = useMemo(()=> COLUMNS, []);
const data = useMemo(()=> countryData, []);
const {
....
setGlobalFilter,
} = useTable({
columns,
data
}, useGlobalFilter, useSortBy);
const{globalFilter} = state;
return (
<>
<GlobalFilter filter={globalFilter} setFilter={setGlobalFilter}/>
<table {...getTableProps()}>
<thead>
{headerGroups.map(headerGroup => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map(column => (
<th {...column.getHeaderProps(column.getSortByToggleProps())}>{column.render('Header')}</th>
))}
</tr>
))}
</thead>
<tbody {...getTableBodyProps()}>
{rows.map((row, i) => {
prepareRow(row)
return (
<tr {...row.getRowProps()}>
{row.cells.map(cell => {
return <td {...cell.getCellProps()}>{cell.render('Cell')}</td>
})}
</tr>
)
})}
</tbody>
</table>
</>
)
}
export default Table
here I want to sort the entire table by default on the basis of new cases column and want toggle sort only on active cases and recovery. as Im new to react i dont know how to provide custom sort..............................................................................................................................................................................................................................................................
you can use :
columns.sort((a, b) => (a.accessor > b.accessor ) ? 1 : -1) More informision at this link: https://flaviocopes.com/how-to-sort-array-of-objects-by-property-javascript/

How could I retrive accessor name inside column header react-table

I have columns as:
const columns = React.useMemo(
() => [
{
Header: "Name",
accessor: "name", // accessor is the "key" in the data
},
{
Header: "Email",
accessor: "email",
}
])
and my table code snippet looks like:
<table
{...getTableProps()}
id="basicTable"
className="table table-bordered action-table table-striped table-hover mb-0"
>
<thead>
{headerGroups.map((headerGroup) => (
<tr {...headerGroup.getHeaderGroupProps()}>
{headerGroup.headers.map((column) => (
<th
{...column.getHeaderProps()}
className="align-top"
>
<div
// {...column.getSortByToggleProps()}
onClick={(e) => {
console.log(
`col ${column.accessor}`
);
}}
>
{column.render("Header")}
</div>
<div>
{column.canFilter
? column.render(
"Filter"
)
: ""}
</div>
</th>
))}
</tr>
))}
</thead>
</table>
Now, here on th, I am trying to retrive the accessor, but I am not being able to do so, on consoling, column.accessor, it returns:
function accessor(row) {
return getBy(row, accessorPath);
}
How, could I get the accessor name so that I could fire api call with col name for sorting?
Update:
accessor function looks as:
Keeping accessor as function helps in handling few other functionalities, for this usecase try to keep another key(eg. sortByBE) for that in column configuration.
Try console.log(cell.value) , you will get the associated cell value.

Creating dynamic table, Object.keys not allowing to return rows of table react

I am creating a dynamic table. If I writing a function like this:-
function renderTable(Category) {
return (
<table>
<tr>
<th>Status</th>
<th>Name</th>
<th>Product</th>
</tr>
{data.data.changer.map(changer=> {
const valuePresent = changer.attack.find(
x => x.unique === category.name
);
if (valuePresent) {
return (
<tr>
<td>{changer.rule_status}</td>
<td>{changer.vendor_rule_name}</td>
<td>{changer.firewall_vendor}</td>
</tr>
);
}
})}
</table>
);
}
It returns the perfect table of how I need it.
But If I try to make the key as dynamic as well like:-
function renderTable(Category) {
return (
<table>
<tr>
<th>Status</th>
<th>Name</th>
<th>Product</th>
</tr>
{Object.keys(data.data).forEach((key, index) => {
if (Category=== key) {
{
data.data[key].map(changer=> {
const valuePresent = changer.attack.find(
x => x.unique === category.name
);
if (valuePresent) {
return (
<tr>
<td>{changer.rule_status}</td>
<td>{changer.vendor_rule_name}</td>
<td>{changer.firewall_vendor}</td>
</tr>
);
}
});
}
}
})}
</table>
);
}
it does not return rows, or and
Any Idea why I want to make key's as well dynamic
Array.prototype.forEach() doesn't return anything, so the JSX in your inner map are never returned. If your goal is to only render the data with the property coverageCategory, I would instead get that property and then do the the map like you have initially, e.g.:
function renderTable(coverageCategory) {
const data = coverageData.data[coverageCategory];
return (
<table>
<tr>
<th>Rule Status</th>
<th>Rule Name</th>
<th>Product name</th>
</tr>
{data.firewall.map(firewall => {
const valuePresent = firewall.mitre_attack.find(
x => x.technique === categorySelected.name
);
if (valuePresent) {
return (
<tr>
<td>{firewall.rule_status}</td>
<td>{firewall.vendor_rule_name}</td>
<td>{firewall.firewall_vendor}</td>
</tr>
);
}
})}
</table>
);
}
An improvement would also be to filter:
data.firewall
.filter((firewall) =>
firewall.mitre_attack.some((x) => x.technique === categorySelected.name)
)
.map((firewall) => (
<tr>
<td>{firewall.rule_status}</td>
<td>{firewall.vendor_rule_name}</td>
<td>{firewall.firewall_vendor}</td>
</tr>
));

Calculating and deleting JSON data

I'm quite confused how to calculate data json that i have. I have data json
"id" : "001","item" : "samsung","quantity" : 2, "price" : $300. first i want to calculate subtotal = quantity*price. and that works. but i dont have idea how to calculate total. anybody can help?
this is js that hold data json
export function DataBarang () {
return [{
"id" : "001",
"item" : "samsung",
"quantity" : 1,
"price" : 300,
},
{
"id" : "002",
"item" : "iphone",
"quantity" : 2,
"price" : 450,
}];
}
and than this is table that display data
import React, { Component } from 'react';
import { DataBarang } from './Barang';
class cart extends Component{
constructor(props) {
super(props)
this.state = {
json: []
}
}
componentDidMount() {
this.setState((prevState) => {
return {
json: DataBarang()
}
})
}
render (){
return (
<table id="cart" className="table table-hover table-condensed">
<thead>
<tr>
<th styles="width:50%" className="text-center">Item</th>
<th styles="width:10%" className="text-center">Price</th>
<th styles="width:8%" className="text-center">Quantity</th>
<th styles="width:22%" className="text-center">Subtotal</th>
<th styles="width:10%" className="text-center">Action</th>
</tr>
</thead>
<tbody>
{this.state.json.map((data, i) => {
var subtotal = data.price*data.quantity;
var total = total+subtotal;
return (
<tr key={i}>
<td data-th="Product">
<div className="row">
<img src={} alt="..." className="img-responsive"/>
<div className="col-sm-10">
<h4 className="nomargin">{data.item}</h4>
</div>
</div>
</td>
<td data-th="Price">Rp.{data.price}</td>
<td data-th="Quantity">
<input type="number" className="form-control" value={data.quantity}/>
</td>
<td data-th="Subtotal" className="text-center">Rp.{subtotal}</td>
<td className="actions" data-th="">
<button className="button is-danger"><i className="fa fa-trash-o"></i></button>
</td>
</tr>);
})}
</tbody>
<tfoot>
<tr>
<td><Link to ="/" className="button is-warning"><i className="fa fa-angle-left"></i> Lanjut Berbelanja</Link></td>
<td colspan="2" className="hidden-xs"></td>
<td className="hidden-xs text-center"><strong>Total Rp. {}</strong></td>
<td>Checkout <i className="fa fa-angle-right"></i></td>
</tr>)
</tfoot>
</table>
);
}
}
export default cart;
and tell me how to delete data using button () onClick
If you're just looking to sum up the entire JSON you receive of quantity * price, then you can do it as a separate calculation.
const json = [{
"id" : "001",
"item" : "samsung",
"quantity" : 1,
"price" : 300,
},
{
"id" : "002",
"item" : "iphone",
"quantity" : 2,
"price" : 450,
}];
const total = json.map(({quantity, price}) => quantity * price)
.reduce((a, b) => a + b)
console.log(total)
In order to handle a delete, make a new function that accepts the id of the element that uses filter to remove it from your this.state.json. Here is a barebones example.
handleDelete(id) {
const filteredJSON = this.state.json.filter(item => {
return item.id !== id
})
this.setState({json: filteredJSON})
}
render() {
return (
<div>
{this.state.json.map((data, i) => {
const id = data.id
return (
<div>
{data.item}
<button onClick={() => this.handleDelete(id)}>
{'delete'}
</button>
</div>
)
})}
</div>
)
}

Categories