How can I implement infinite scrolling on a table using react-virualised? - javascript

I have been struggling with react-virtualised docs They have full-featured example tables.
All I want is simple infinite scrolling for my table. Please if anyone can help.
I just want to render my content when it's visible on the screen.
NOTE: I am not pulling the data from any API I have static data(an array of objects) saved into my local folder.
Please see a screenshot of my app below.
Below is my code.
const renderRows = items.map((data, index) => {
return (
<tr
className="table__row"
key={data.id}
onClick={() => onRowClick(data.id)}
>
<td style={{ marginRight: '2px' }}>
<img
onClick={(e) => {
toggleStarSelect(e, data.id);
}}
src={Star}
className="star"
alt="star"
style={{ padding: '2px' }}
/>
{data['#']}
</td>
<td>
<ImageLoadHandler
isloaded={isloaded}
handleImage={handleImage}
data={data}
/>
<span style={{ padding: '10px' }}>{data.Name}</span>
<span
style={{
backgroundColor: 'lightgray',
opacity: '0.5',
fontSize: '13px',
}}
>
{data.Symbol}
</span>
</td>
<td>{data.Price}</td>
<td>{data['1h']}</td>
<td className={data['24h'] > 0 ? 'green' : 'red'}>
{data['24h'] > 0 ? (
<img className="arrowicon" src={SortUpGreen} alt="sort-up-green" />
) : (
<img className="arrowicon" src={SortDownRed} alt="sort-down-red" />
)}
{data['24h']}%
</td>
<td>{data['7d']}</td>
<td>{data['Mkt Cap']}</td>
<td>{data['24h Vol']}</td>
<td style={{ padding: '0', paddingRight: '8px' }}>
<Suspense fallback={<div className="loading">loading...</div>}>
<Graph data={data} idx={index} />
</Suspense>
</td>
</tr>
);
});
return (
<div className="app">
<header>
<Header />
</header>
<table className="app__table">
<thead className="app__tablehead">
<tr>
<th
onClick={() => requestSort('#')}
className={getClassNamesFor('#')} //returns ascending or descending
>
#
</th>
<th
onClick={() => requestSort('Name')}
className={getClassNamesFor('Name')}
>
Coin
</th>
<th
onClick={() => requestSort('Price')}
className={getClassNamesFor('Price')}
>
Price
</th>
<th
onClick={() => requestSort('1h')}
className={getClassNamesFor('1h')}
>
1h
</th>
<th
onClick={() => requestSort('24h')}
className={getClassNamesFor('24h')}
>
24h
</th>
<th
onClick={() => requestSort('7d')}
className={getClassNamesFor('7d')}
>
7d
</th>
<th
onClick={() => requestSort('Mkt Cap')}
className={getClassNamesFor('Mkt Cap')}
>
Mkt Cap
</th>
<th
onClick={() => requestSort('24h Vol')}
className={getClassNamesFor('24h Vol')}
>
24h Vol
</th>
<th className="nohover">Last 7 days</th>
</tr>
</thead>
<tbody>{renderRows}</tbody>
</table>
</div>
);

A working example of infinite scroll on a table element. Also a working a repl.
import React, {useState, useEffect} from 'react';
import './App.css';
function App() {
let items = [];
for (let i = 0; i < 100; i++) {
items.push({
key: 'foo' + i,
value: 'bar' + i,
});
}
let dataTable = React.createRef();
const [list, setList] = useState({
itemsDisplayed: 20,
data: items.slice(0, 20),
});
let onScroll = () => {
let tableEl = dataTable.current;
if (tableEl.scrollTop === (tableEl.scrollHeight - tableEl.offsetHeight)) {
if (list.itemsDisplayed + 10 <= items.length) {
setList({
itemsDisplayed: list.itemsDisplayed + 10,
data: items.slice(0, list.itemsDisplayed + 10),
});
}
}
};
return (
<div className="App">
<table id="data-table" ref={dataTable} onScroll={onScroll}>
<tbody>
{list.data.map((item) => {
return (
<tr key={item.key}>
{item.value}
</tr>
);
})}
</tbody>
</table>
</div>
);
}
export default App;
Also to mention, the problem of scrolling firing only once solved by this question. The point is to use React's built-in onScroll event.

Related

When click on user open a modal with full information of the user

**I am passing the user through to the modal ViewUser to show it data but it always show the same user when clicking in different user, I need to know how can I specify the user who I need to show their data, I send it in ViewUser component as user **
const UserList = () => {
const [confirmDel, setConfirmDel] = useState(false);
const [showData, setShowData] = useState(false);
const usersList = useAppSelector((state) => state.users);
const handleShowDataOpen = () => {
setShowData(true);
};
const handleShowDataClose = () => {
setShowData(false);
};
return (
<>
<div className={styles.main_container}>
<h1>Users List</h1>
{usersList.length === 0 ? (
<span className={styles.empty_container}>
No current registered users
</span>
) : (
<>
<TableContainer component={Paper}>
<Table aria-label="simple table" size="small">
<TableHead>
<TableRow>
<TableCell>Username</TableCell>
<TableCell>First Name</TableCell>
<TableCell>Age</TableCell>
<TableCell>Action</TableCell>
</TableRow>
</TableHead>
<TableBody>
{usersList.map((user) => (
<TableRow key={user.username}>
<TableCell>
<Button variant="text" onClick={handleShowDataOpen}>
{user.username}
</Button>
<ViewUser showData={showData} user={user} handleShowDataClose={handleShowDataClose} />
</TableCell>
<TableCell>{user.firstName}</TableCell>
<TableCell>{user.age}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</>
)}
</div>
</>
);
};
export default UserList;
Your boolean state for showData is being set to true, which means that the ViewUser component is being shown for every user at the same time.
Instead, you could store the index of the single user which you want to show at a single time.
import { useState } from "react";
import { data } from "./data";
const UserList = () => {
const [showData, setShowData] = useState(null);
const usersList = data;
const handleShowDataOpen = (index) => {
setShowData(index);
};
const handleShowDataClose = () => {
setShowData(null);
};
return (
<>
<div>
<h1>Users List</h1>
{usersList.length === 0 ? (
<span>No current registered users</span>
) : (
<>
<div>
<table>
<thead>
<tr>
<th>Username</th>
<th>First Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
{usersList.map((user, index) => (
<tr key={user.id}>
<td>
<button
variant="text"
onClick={() => handleShowDataOpen(index)}
>
{user.firstName} {user.lastName}
</button>
<ViewUser
showUser={showData === index}
user={user}
handleShowDataClose={handleShowDataClose}
/>
</td>
<td>{user.firstName}</td>
<td>{user.age}</td>
</tr>
))}
</tbody>
</table>
</div>
</>
)}
</div>
</>
);
};
export default UserList;
const ViewUser = ({ user, showUser, handleShowDataClose }) => {
return showUser ? (
<div
style={{
position: "absolute",
background: "rgba(255,255,255,0.5)",
padding: 20
}}
>
<pre>{JSON.stringify(user)}</pre>
<button onClick={handleShowDataClose}>Close</button>
</div>
) : null;
};
Alternatively, create a separate User component, and keep the open state inside it instead of in UserList.
import { useState } from "react";
import { data } from "./data";
const UserList = () => {
const usersList = data;
return (
<>
<div>
<h1>Users List</h1>
{usersList.length === 0 ? (
<span>No current registered users</span>
) : (
<>
<div>
<table>
<thead>
<tr>
<th>Username</th>
<th>First Name</th>
<th>Age</th>
</tr>
</thead>
<tbody>
{usersList.map((user) => (
<User user={user} />
))}
</tbody>
</table>
</div>
</>
)}
</div>
</>
);
};
export default UserList;
const User = ({ user }) => {
const [isOpen, setIsOpen] = useState(false);
return (
<tr key={user.id}>
<td>
<button variant="text" onClick={() => setIsOpen(true)}>
{user.firstName} {user.lastName}
</button>
<ViewUser
showUser={isOpen}
user={user}
handleShowDataClose={() => setIsOpen(false)}
/>
</td>
<td>{user.firstName}</td>
<td>{user.age}</td>
</tr>
);
};
const ViewUser = ({ user, showUser, handleShowDataClose }) => {
return showUser ? (
<div
style={{
position: "absolute",
background: "rgba(255,255,255,0.5)",
padding: 20
}}
>
<pre>{JSON.stringify(user)}</pre>
<button onClick={handleShowDataClose}>Close</button>
</div>
) : null;
};

checked box need to be click 2 time to make it check i have tried with onclick as well it is giving same behaviour i need to disable button oncheck

**react js **
what I want is when i check any checkbox from the table in the particular button gets disabled but i have to click the checkbox two times to make it check i have also tried with onClick it is also giving the same output Please help me i am get the data through api call form localost only in useEffect and storing the data in a state Array with addon key to make
checkbox checked and button disabled and the state checked is to toggel the value of checkbox and button; But the only problem is User have to click it 2 times i am not able to figure out
const Table1 = () => {
const [supervisors, setSupervisors] = useState([]);
const [checked, setChecked] = useState(false);
useEffect(() => {
const fetchTableList = async () => {
const { data } = await axios("http://localhost:4000/users");
let newData = data.map((item) => {
item.checked = false;
item.disabled = false;
return item;
});
setSupervisors(newData);
};
fetchTableList();
}, []);
console.log(supervisors);
return (
<div className="table-component" style={{ minHeight: "91vh" }}>
<h2 className="main-heading text-center">Supervisor Mapping</h2>
<Table striped bordered hover className="table text-center">
<thead className="heading">
<tr style={{ fontSize: "1.125rem" }}>
<th className="table-heading">OID</th>
<th className="table-heading">Supervisor </th>
<th className="table-heading">Title</th>
<th className="table-heading">Project</th>
<th className="table-heading">Industry</th>
<th className="table-heading">Supervisee</th>
<th className="table-heading">Receiver</th>
<th className="table-heading">Actions</th>
</tr>
</thead>
<tbody>
{supervisors.map((item, index) => (
<tr key={item.supervisorId} style={{ fontSize: "0.938rem" }}>
<td>{item.supervisorId}</td>
<td className="mx-5">{item.supervisor} </td>
<td>{item.title}</td>
<td>{item.project}</td>
<td>{item.industry}</td>
<td
style={
item.supervisee.length > 5
? { backgroundColor: "red", color: "white" }
: item.supervisee.length > 1
? { backgroundColor: "yellowgreen", color: "white" }
: { backgroundColor: "#FFD580", color: "white" }
}
>
{item.supervisee.length}{" "}
</td>
<td>
{" "}
<input
className="checkBox"
type="checkbox"
onChange={() => {
setChecked(!checked);
item.checked = checked;
}}
checked={item.checked}
/>
</td>
<td>
<Button
className="fas fa-eye"
disabled={item.checked}
id={index}
data-id={item.supervisorId}
data-name={item.supervisor}
></Button>
</td>
</tr>
))}
</tbody>
</Table>
</div>
)}
Do not mutate the state directly.
onChange={() => {
setChecked(!checked);
item.checked = checked; //
}}
checked={item.checked}
Always update a clone of the state.
onChange={() => {
// create a clone of the supervisors array
const newSupervisors = supervisors.slice(0);
// mutate the cloned array
newSupervisors[index].checked = !item.checked;
// replace the state with the mutated clone
setSupervisors(newSupervisors);
}}
This is not necessary.
const [checked, setChecked] = useState(false);

while printing a pdf table breaking and calculations

I have a table where while printing table is getting split in multiple pages , but i have few calculations when moving to next page
so while printing here the table row is getting split into two pages , and i want to add the remaining data to calculate what is the total in this page and carry forward that sum to next page , is there any way to identify this table brake ?
Sharing the html table structure :
<table
id="details_report"
style={{
fontSize:12,
borderCollapse: 'collapse',
border: '1px solid black',
width: '100%',
margin: '0px',
}}
>
<thead>
<tr>
<td
colspan="3"
>
Name of table
</td>
</tr>
<tr style={{ borderTop: '1px solid black' }}>
<td
style={{ paddingLeft: 15, fontWeight: 'bold' }}
>
Note
</td>
<td
style={{
fontWeight: 'bold',
paddingLeft: 12,
}}
>
PARTICULARS
</td>
<td
data-a-h="end"
style={{
textAlign: 'center',
fontWeight: 'bold',
paddingRight: 20,
}}
>
As at 31/03/2020
</td>
</tr>
</thead>
<tbody>
{Data &&
Data.map((el, i) => (
<>
<tr>
<td
>
{el.note_number}{G_Children[el.detail_number - 1]})
</td>
<td
>
<strong>{el.account}</strong>
</td>
<td/>
</tr>
{el.children.map((el2, j) => (
<>
<tr>
<td />
<td>{el2.account}</td>
<td >{el2.total}</td>
</tr>
{/* after every 5 entry need space */}
{el.children.length !== j + 1 &&
(j + 1) % 5 === 0 && (
<tr style={{ height: 15 }}>
<td className="emptytd" colspan="3" />
</tr>
)}
</>
))}
<tr>
<td colSpan="2"/>
<td>{el.total}</td>
</tr>
</>
))}
</tbody>
</table>
For Json Data i have attached a file

How to define the length of the array when using map function and display the rows which have data?

I have created a button with the collapse effect and In that creating a simple table then I created an excel file and in that created a two table one display the button content and second table display the table content. when I run my code then an unlimited button is created and only 3 buttons display the data which I have stored in the table.
Here is my code:
import React, { useState } from 'react'
import { Table } from 'react-bootstrap'
import * as XLSX from 'xlsx'
import Accordion from './component/accordion'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faTrashAlt } from '#fortawesome/free-solid-svg-icons'
import './App.css'
function App() {
const[items, setItems] = useState([])
const readExcel=(file) => {
const promise = new Promise((resolve, reject)=>{
const fileReader = new FileReader();
fileReader.readAsArrayBuffer(file);
fileReader.onload=(e)=>{
const bufferArray = e.target.result;
const wb = XLSX.read(bufferArray, {type: "buffer"});
const wsname = wb.SheetNames[0];
const ws = wb.Sheets[wsname];
const data = XLSX.utils.sheet_to_json(ws);
resolve(data);
};
fileReader.onerror=(error) => {
reject(error);
};
});
promise.then((d)=>{
setItems(d);
console.log(d)
});
};
return(
<div className="container-fluid">
<section className="heading">
<h4>Products Details</h4>
<input type="file" className="input-field" name="Upload File" onChange={(e) =>{
const file=e.target.files[0];
readExcel(file);
}} />
</section>
{items.map((d) => (
<Accordion
title={
<tr key={d.ID} className="btn-heading">
<td style={{padding: "0px 36px"}}>{d.ID}</td>
<td style={{padding: "0px 16px"}}>{d.Mail}</td>
<td style={{padding: "0px 67px"}}>{d.Name}</td>
<td style={{padding: "0px 3px"}}>{d.PhoneNo}</td>
<td style={{padding: "0px 98px"}}>{d.City}</td>
<td style={{padding: "0px 6px"}}>{d.Date}</td>
<td style={{padding: "0px 120px"}}>{d.Time}</td>
</tr>
}
content={
<div>
<p className="header">
<span className="header-content">Shipping Address:</span>
292 Naqshband Colony. Near rabbania Mosque. Multan
</p>
<Table size="sm">
<thead>
<tr>
<th>#</th>
<th style={{width:"15%",textAlign:"center"}}>Article No</th>
<th style={{width:"30%"}}>Product Name</th>
<th style={{width:"20%" ,textAlign:"center"}}>Quantity</th>
<th style={{width:"15%" ,textAlign:"center"}}>Price</th>
<th style={{width:"15%" ,textAlign:"center"}}>Total Amount</th>
</tr>
</thead>
<tbody>
{items.map((d) => (
<tr key={d.ArticleNo}>
<colgroup>
<FontAwesomeIcon icon={faTrashAlt} />
</colgroup>
<td>{d.ArticleNo}</td>
<td style={{textAlign:"left"}}> {d.ProductName}</td>
<td>{d.Quantity}</td>
<td>{d.Price}</td>
<td>{d.TotalAmount}</td>
</tr>
))}
</tbody>
</Table>
</div>
}
/>
))}
</div>
);
}
export default App;
And here is my excel file which I have created two tables:
Excel File Tables
here is the output of my project the unlimited buttons:
Code Output

React js - How to select all rows ID from HTML table

i am trying to select all rows Id that contains in html table by one click i tried to do this but that function does not work and array list shows empty how to do that i can select all rows id by single checkbox and i want all rows id in selectedItems as list form . here is my code that i did.
this.state = {
checkedBoxCheck: false,
selectedItems: [],
stats: [],
}
componentDidMount() {
...
}
toggleSelectAll() {
let selectedItems = [];
if (this.state.selectAll === 0) {
this.state.stats.forEach(x => {
selectedItems[x.id] = true;
});
}
this.setState({
selectedItems: selectedItems,
checkedBoxCheck: true
});
console.log(selectedItems);
}
<thead>
<tr style={{ marginTop: "-88px" }}>
<th class="active" style={{ width: "20px" }}>
<input
type="checkbox"
class="select-all checkbox"
onChange={this.onChange}
name="first_name"
onClick={this.toggleSelectAll.bind(this)}
/>
</th>
<th className="" style={{ width: "20px" }}>
{t("Id")}
</th>
</thead>
<tbody>
{stats.map((c, i) => (
<tr key={c.id}>
<td>
<input
type="checkbox"
id="togBtn"
className="checkbox"
name="selectOptions"
onClick={() => this.onItemSelect(c.id)}
/>
</td>
<td>{c.id}</td>
</tbody>

Categories