How to reset ant design table selected rows? - javascript

I am using ant design table component and I have selected rows.
I want onClick reset selected rows.
I can not find out where it stores selected rows.
const rowSelection = {
onChange: (selectedRowKeys, rows) => {
this.setState({
selectedRowsArray: [...rows]
});
},
};
<Table rowSelection={rowSelection} columns={columns} dataSource={paymentsHistory} />
Any Idea how to clear selected rows?

rowSelection also takes selectedRowKeys property that will help you control the selected rows at any point in time.
const { selectedRowsArray } = this.state;
const rowSelection = {
selectedRowKeys: selectedRowsArray,
onChange: (selectedRowKeys, rows) => {
this.setState({
selectedRowsArray: [...rows]
});
},
};
<Table rowSelection={rowSelection} columns={columns} dataSource={paymentsHistory} />
Codesandbox Example | Antd Docs

We can also do this with hooks:
import { useState } from 'react';
import { Table, Button } from 'antd';
function App() {
const [selectedRowKeys, setRowKeys] = useState([]);
const [loading, setLoading] = useState([]);
const start = () => {
setRowKeys([]);
};
const onSelectChange = selectedRowKeys => {
setRowKeys(selectedRowKeys);
};
const rowSelection = {
selectedRowKeys,
onChange: onSelectChange,
};
const dataSource = [
{
key: '1',
name: 'Mike',
age: 32,
address: '10 Downing Street',
},
{
key: '2',
name: 'John',
age: 42,
address: '10 Downing Street',
}, enter code here
];
const columns = [
{
title: 'Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Age',
dataIndex: 'age',
key: 'age',
},
{
title: 'Address',
dataIndex: 'address',
key: 'address',
},
];
return (
<div className="App">
<Button type="primary" onClick={start} >
Reload
</Button>
<Table dataSource={dataSource} columns={columns} rowSelection={rowSelection} />;
</div>
);
}
export default App;

Maybe following example will make it clear for you:
import React, { useState } from "react";
import { Table, Button } from "antd";
import "antd/dist/antd.css";
import "./index.css";
export default function App() {
const columns = [
{
title: "Currency",
dataIndex: "сurrency",
key: "сurrency"
}
];
const data = [
{
key: "EUR",
сurrency: "€"
},
{
key: "USD",
сurrency: "$"
},
{
key: "RUB",
сurrency: "₽"
}
];
const [selectedRowsArray, setSelectedRowsArray] = useState([]);
const rowSelection = {
selectedRowKeys: selectedRowsArray,
onChange: (key) => {
setSelectedRowsArray(key);
exchangeMoney(key[0]);
}
};
function exchangeMoney(key) {
console.log(key);
}
return (
<>
<Table
columns={columns}
dataSource={data}
rowSelection={{ type: "radio", ...rowSelection }}
/>
<Button className="clear-btn" onClick={() => setSelectedRowsArray([])}>
CLEAR
</Button>
</>
);
}
see in codesandbox

Related

react js state in parent component isn't re rendering in child component

so i am trying to make a filter for my products. And for that i initialised a state in a component called Product that has all the filters. And then, based on the input of the checkboxes that are in a child component that is called Category, the filter state changes.
here is my code :
Product.jsx:
import { useState } from "react";
import Filter from "./Filter.jsx";
import styles from "../styles/products.module.css";
const products = {
prod1: {
id: 1,
name: "prod1",
category: "laptops",
price: "80",
description: { brand: "lenovo", processor: "intel core i7" },
},
prod2: {
id: 2,
name: "prod2",
category: "laptops",
price: "10",
description: { brand: "lenovo", processor: "intel core i7" },
},
prod3: {
id: 3,
name: "prod3",
category: "laptops",
price: "100",
description: { brand: "msi", processor: "intel core i5" },
},
prod4: {
id: 4,
name: "prod4",
category: "laptops",
price: "200",
description: { brand: "msi", processor: "intel core i3" },
},
prod5: {
id: 5,
name: "prod5",
category: "phones",
price: "50",
description: { brand: "samsung", ram: "8gb", storage: "64gb" },
},
prod6: {
id: 6,
name: "prod6",
category: "phones",
price: "50",
description: { brand: "infinix", ram: "4gb", storage: "128gb" },
},
prod7: {
id: 7,
name: "prod7",
category: "phones",
price: "50",
description: { brand: "oppo", ram: "8gb", storage: "256gb" },
},
prod8: {
id: 8,
name: "prod8",
category: "accessories",
price: "99",
description: { type: "keyboard" },
},
prod9: {
id: 9,
name: "prod9",
category: "accessories",
price: "75",
description: { type: "mouse" },
},
};
function Products() {
const filter = {
laptops: {
brand: [],
processor: [],
},
phones: {
brand: [],
ram: [],
storage: [],
},
accessories: {
type: [],
},
};
const [filterList, setFilterList] = useState(filter);
const [category, setCategory] = useState("all");
const [range, setRange] = useState(9999);
const getFilterState = () => {
return filterList;
};
const setFilterState = (list) => {
setFilterList(list);
};
return (
<div className={styles.productsContainer}>
<Filter
range={[range, setRange]}
category={[category, setCategory]}
getfilterList={getFilterState}
setFilterState={setFilterState}
/>
<table className={styles.productsListContainer}>
<tr className={styles.tableColumn}>
<th className={styles.tableRow}>id</th>
<th className={styles.tableRow}>Name</th>
<th className={styles.tableRow}>price</th>
</tr>
{Object.keys(products).map((key) => {
let flag = true;
const product = products[key];
const categ = product.category;
if (
(categ === category || category === "all") &&
product.price <= range
) {
Object.entries(filter[categ]).forEach(([key, value]) => {
if (
!(
value.length === 0 || value.includes(product.description[key])
)
) {
flag = false;
}
});
if (flag) {
return (
<tr className={styles.tableColumn} key={product.id}>
<td className={styles.tableRow}>{product.id}</td>
<td className={styles.tableRow}>{product.name}</td>
<td className={styles.tableRow}>{product.price}</td>
</tr>
);
}
return null;
}
return null;
})}
</table>
</div>
);
}
export default Products;
Filter.jsx:
import CategoryComponent from "./Category";
import styles from "../styles/filter.module.css";
function Filter({
filters,
dispatch,
category,
getfilterList: filterList,
setFilterState: setFilterList,
range: rangeState,
}) {
const [Category, setCategory] = category;
const [Range, setRange] = rangeState;
const handleCategoryChanged = (event, categ, key) => {
let list = filterList();
if (list[categ][key].includes(event.currentTarget.value)) {
list[categ][key] = list[categ][key].filter(
(val) => val !== event.currentTarget.value
);
} else {
list[categ][key].push(event.currentTarget.value);
}
setFilterList(list);
if (Category !== categ) {
setCategory(categ);
} else {
let flag = false;
Object.keys(filterList()[categ]).forEach((key) => {
const obj = filterList()[categ][key];
if (obj.length !== 0) flag = true;
});
if (!flag) {
setCategory("all");
}
}
};
const handleRangeChanged = (event) => {
setRange(event.currentTarget.value);
};
return (
<div className="filter-container">
<h1>{Category}</h1>
<CategoryComponent
filterList={filterList()}
setFilterList={setFilterList}
category={Category}
handleCategoryChanged={handleCategoryChanged}
categories={{
brand: ["lenovo", "msi", "asus"],
processor: ["intel core i3", "intel core i5", "intel core i7"],
}}
>
laptops
</CategoryComponent>
<CategoryComponent
filterList={filterList()}
setFilterList={setFilterList}
handleCategoryChanged={handleCategoryChanged}
category={Category}
categories={{
brand: ["samsung", "infinx", "oppo"],
ram: ["8gb", "4gb", "2gb"],
storage: ["64gb", "128gb", "256gb"],
}}
>
phones
</CategoryComponent>
<CategoryComponent
filterList={filterList()}
setFilterList={setFilterList}
category={Category}
handleCategoryChanged={handleCategoryChanged}
categories={{
type: ["keyboard", "mouse", "screen"],
}}
>
accessories
</CategoryComponent>
<div className={styles.priceRangeContainer}>
<input
type="range"
min="0"
max="9999"
className={styles.priceRange}
value={Range}
onChange={handleRangeChanged}
/>
<span>{Range}DT</span>
</div>
</div>
);
}
export default Filter;
Category.jsx
import React from "react";
import { useState, useEffect } from "react";
import styles from "../styles/category.module.css";
import arrow from "../img/angle-up-solid-svgrepo-com.svg";
export default function Category({
handleCategoryChanged,
children,
categories,
category,
filterList,
setFilterList,
}) {
const [hiddenClass, setHiddenClass] = useState(styles.hidden);
const handleClick = () => {
if (hiddenClass) setHiddenClass("");
else setHiddenClass(styles.hidden);
};
return (
<div>
<h5>{category}</h5>
<div onClick={handleClick} className={styles.categoryBox}>
{children} <img style={{ width: 15 }} src={arrow} alt="" />
</div>
<div className={styles.hiddenScroll + " " + hiddenClass}>
{Object.entries(categories).map(([key, value]) => {
return (
<div key={key}>
<h5>{key}:</h5>
<ul>
{value.map((val) => {
console.log(filterList);
return (
<li key={val}>
<input
type="checkbox"
name={val}
id={val}
value={val}
onChange={(e) =>
handleCategoryChanged(e, children, key)
}
/>
<label htmlFor={val}>{val}</label>
</li>
);
})}
</ul>
</div>
);
})}
</div>
</div>
);
}
The problem is when i run my program the state changes when i check an only one checkbox, but when i click on more checkboxes nothing changes.
EDIT:
my components hierarchy :
products.jsx
filter.jsx
Category.jsx
in products.jsx :
i have a state filterList that has all the filters i need.
const filter = {
laptops: {
brand: [],
processor: [],
},
phones: {
brand: [],
ram: [],
storage: [],
},
accessories: {
type: [],
},
};
const [filterList, setFilterList] = useState(filter);
in Filter.jsx:
i have state filterList that was passed as a prop from the Products component.
and a function that handles any checkbox change from it's child component.
const handleCategoryChanged = (event, categ, key) => {
let list = filterList();
//testing if the value is already in the filterList if true we remove it
if (list[categ][key].includes(event.currentTarget.value)) {
list[categ][key] = list[categ][key].filter(
(val) => val !== event.currentTarget.value
);
} else {
// else we add it to the list
list[categ][key].push(event.currentTarget.value);
}
setFilterList(list);
Category.jsx:
here i created all my checkboxes with the onChange event.
But the problem is when more than one checkbox gets changed, my filterList state does not get re rendered.
You missed the useState in your Filter.jsx
Replacing
const [Category, setCategory] = category;
const [Range, setRange] = rangeState;
With
const [Category, setCategory] = useState(category);
const [Range, setRange] = useState(rangeState);
A small working example could be found at code sandbox
⚠️ You did not provide the parent of Filter.jsx so in the example only the laptop brands are working

How to use drag and drop in ant design?

What I want is an example about how to make the drag and drop of my Table that works properly, but I cannot figure out how to make it works in (functional components)
My code :
function Preview() {
const { name } = useParams();
const [fieldsOfForm, setFieldsOfForm] = useState([]);
const [selectedForm, setSelectedForm] = useState([]);
const columns = [
{
title: 'Posição',
dataIndex: 'pos',
width: 30,
className: 'drag-visible',
render: () =>
<MenuOutlined style={{ cursor: 'grab', color: '#999' }}/>
},
{
title: "Form Name",
dataIndex: "field",
key: "field",
render: (text) => <a>{text}</a>,
},
{
title: "Tipo",
dataIndex: "fieldtype",
key: "fieldtype",
},
];
useEffect(() => {
let mounted = true;
let loadingStates = loading;
if (mounted) {
setFieldsOfForm(location.state);
loadingStates.allFields = false;
setLoading(false);
}
return () => (mounted = false);
}, [selectedForm]);
return (
//Some jsx....
<Row gutter={1}>
<Col span={1}></Col>
<Table dataSource={fieldsOfForm}
columns= {columns}/>
</Row>
// More jsx...
);
}
export default Preview;
Everything that I found on internet about this drag and drop from the lib of antd is in class component , but I wanted to make it works in my functional one.
Example that I found :
multi row drag-able table (antd)
I want some example in function component if someone has tried it already and could help me ?
Here's a functional working example:
import React from "react";
import "antd/dist/antd.css";
import { Table } from "antd";
import {
sortableContainer,
sortableElement,
sortableHandle
} from "react-sortable-hoc";
import { MenuOutlined } from "#ant-design/icons";
const data = [
{
key: "1",
name: "John Brown",
age: 32,
address: "New York No. 1 Lake Park",
index: 0
},
{
key: "2",
name: "Jim Green",
age: 42,
address: "London No. 1 Lake Park",
index: 1
},
{
key: "3",
name: "Joe Black",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 2
},
{
key: "4",
name: "4",
age: 32,
address: "New York No. 1 Lake Park",
index: 3
},
{
key: "5",
name: "5",
age: 42,
address: "London No. 1 Lake Park",
index: 4
},
{
key: "6",
name: "6",
age: 32,
address: "Sidney No. 1 Lake Park",
index: 5
}
];
const DragHandle = sortableHandle(({ active }) => (
<MenuOutlined style={{ cursor: "grab", color: active ? "blue" : "#999" }} />
));
const SortableItem = sortableElement((props) => <tr {...props} />);
const SortableContainer = sortableContainer((props) => <tbody {...props} />);
function SortableTable() {
const [dataSource, setDataSource] = React.useState(data);
const [selectedItems, setSelectedItems] = React.useState([]);
const getColumns = () => {
return [
{
title: "Sort",
dataIndex: "",
width: 30,
className: "drag-visible",
render: (d, dd, i) => (
<>
<DragHandle active={selectedItems.includes(i)} />
</>
)
},
{
title: "Name",
dataIndex: "name",
className: "drag-visible"
},
{
title: "Age",
dataIndex: "age"
},
{
title: "Address",
dataIndex: "address"
}
];
};
const merge = (a, b, i = 0) => {
let aa = [...a];
return [...a.slice(0, i), ...b, ...aa.slice(i, aa.length)];
};
const onSortEnd = ({ oldIndex, newIndex }) => {
let tempDataSource = dataSource;
if (oldIndex !== newIndex) {
if (!selectedItems.length) {
let movingItem = tempDataSource[oldIndex];
tempDataSource.splice(oldIndex, 1);
tempDataSource = merge(tempDataSource, [movingItem], newIndex);
} else {
let filteredItems = [];
selectedItems.forEach((d) => {
filteredItems.push(tempDataSource[d]);
});
let newData = [];
tempDataSource.forEach((d, i) => {
if (!selectedItems.includes(i)) {
newData.push(d);
}
});
tempDataSource = [...newData];
tempDataSource = merge(tempDataSource, filteredItems, newIndex);
}
setDataSource(tempDataSource);
setSelectedItems([]);
}
};
const DraggableContainer = (props) => (
<SortableContainer
useDragHandle
disableAutoscroll
helperClass="row-dragging"
onSortEnd={onSortEnd}
{...props}
/>
);
const DraggableBodyRow = ({ className, style, ...restProps }) => {
// function findIndex base on Table rowKey props and should always be a right array index
const index = dataSource.findIndex(
(x) => x.index === restProps["data-row-key"]
);
return (
<SortableItem
index={index}
{...restProps}
selected={selectedItems.length}
onClick={(e) => {
if (e.ctrlKey || e.metaKey) {
selectedItems.includes(index)
? selectedItems.splice(selectedItems.indexOf(index), 1)
: selectedItems.push(index);
setSelectedItems(selectedItems);
} else {
setSelectedItems([]);
}
}}
/>
);
};
return (
<>
<h3>"CNTRL + Click" to select multiple items</h3>
<Table
pagination={false}
dataSource={dataSource}
columns={getColumns()}
rowKey="index"
components={{
body: {
wrapper: DraggableContainer,
row: DraggableBodyRow
}
}}
/>
{selectedItems.length ? <>{selectedItems.length} items selected </> : ""}
</>
);
}
You can play with it in Sandbox

react Material-table unable to change each icon set color? [duplicate]

This question already has answers here:
How can I change the color of material-table icons of onRowAdd, onRowUpdate, onRowDelete?
(2 answers)
Closed 1 year ago.
I am using the material-table library and trying to change each icon color. Would you please help me to do so? I tried custom CSS but it's changing all icon color at once not the specific one?
here is my code sandbox link.
In short: I want to change color of each of three icons add, edit, delete
Here is my code I am using a material-table library with material-ui. Also is it possible to change these default icons?
List.js
import React, { useState } from 'react';
import './App.css';
import MaterialTable from 'material-table'
import makeStyles from "#material-ui/core/styles/makeStyles";
const useStyles = makeStyles(theme => ({
rootTable: {
'& .MuiIconButton-colorInherit' : {
color: '#6a2cd8'
},
'& .MuiIconButton-root .MuiIconButton-colorInherit': {
color: 'red'
},
width: theme.spacing(150)
}
}));
const empList = [
{ id: 1, name: "Neeraj", email: 'neeraj#gmail.com', phone: 9876543210, city: "Bangalore" },
{ id: 2, name: "Raj", email: 'raj#gmail.com', phone: 9812345678, city: "Chennai" },
{ id: 3, name: "David", email: 'david342#gmail.com', phone: 7896536289, city: "Jaipur" },
{ id: 4, name: "Vikas", email: 'vikas75#gmail.com', phone: 9087654321, city: "Hyderabad" },
]
function App() {
const [data, setData] = useState(empList)
const columns = [
{ title: "ID", field: "id", editable: false },
{ title: "Name", field: "name" },
{ title: "Email", field: "email" },
{ title: "Phone Number", field: 'phone', },
{ title: "City", field: "city", }
]
const classes = useStyles();
return (
<div className="App">
<h1 align="center">React-App</h1>
<h4 align='center'>Material Table with CRUD operation</h4>
<div className={classes.rootTable}>
<MaterialTable
title="Employee Data"
data={data}
columns={columns}
editable={{
onRowAdd: (newRow) => new Promise((resolve, reject) => {
const updatedRows = [...data, { id: Math.floor(Math.random() * 100), ...newRow }]
setTimeout(() => {
setData(updatedRows)
resolve()
}, 2000)
}),
onRowDelete: selectedRow => new Promise((resolve, reject) => {
const index = selectedRow.tableData.id;
const updatedRows = [...data]
updatedRows.splice(index, 1)
setTimeout(() => {
setData(updatedRows)
resolve()
}, 2000)
}),
onRowUpdate:(updatedRow,oldRow)=>new Promise((resolve,reject)=>{
const index=oldRow.tableData.id;
const updatedRows=[...data]
updatedRows[index]=updatedRow
setTimeout(() => {
setData(updatedRows)
resolve()
}, 2000)
})
}}
options={{
actionsColumnIndex: -1, addRowPosition: "first"
}}
/>
</div>
</div>
);
}
export default App;
You can import icons you wish to change their color from #material-ui/icons, change the color you want, and pass them as icons prop to MaterialTable: codesandbox.
import { Edit } from "#material-ui/icons";
...
icons={{
Edit: React.forwardRef((props, ref) => (
<Edit style={{ color: "green" }} {...props} ref={ref} />
))
}}

Is this the best way to convert a class component to a hook component?

So this is the code i am trying to get to work with useState,
https://codesandbox.io/s/rdg-cell-editing-forked-nc7wy?file=/src/index.js:0-1146
Here is my attempt and the error I am getting is × TypeError: Cannot read property 'length' of undefined
import React, { useState } from "react";
import ReactDataGrid from "react-data-grid";
import "./styles.css";
const App = () => {
const columns = [
{ key: "id", name: "ID", editable: true },
{ key: "title", name: "Title", editable: true },
{ key: "complete", name: "Complete", editable: true }
];
const [rows, setRows] = useState([
{ id: 0, title: "Task 1", complete: 20 },
{ id: 1, title: "Task 2", complete: 40 },
{ id: 2, title: "Task 3", complete: 60 }
]);
onGridRowsUpdated = ({ fromRow, toRow, updated }) => {
setRows((state) => {
const rows = rows.slice();
for (let i = fromRow; i <= toRow; i++) {
rows[i] = { ...rows[i], ...updated };
}
return { rows };
});
};
return (
<ReactDataGrid
columns={columns}
rowGetter={(i) => rows[i]}
rowsCount={3}
onGridRowsUpdated={onGridRowsUpdated}
enableCellSelect={true}
editable={true}
/>
);
};
export default App;
So I am using the code from https://codesandbox.io/s/rdg-cell-editing-forked-nc7wy?file=/src/index.js:0-1146 to try and make this work with useState but I get the error ×
TypeError: Cannot read property 'length' of undefined
I think you need to pass arguments to onGridRowsUpdated.
<ReactDataGrid
...
onGridRowsUpdated={() => { onGridRowsUpdated(fromRow, toRow, updated) }}
...
/>

How to perform inline edit while using react-table or react-table-6?

I'm trying to perform CRUD operations in React using react-table-6 library, since its lightweight and has basic functionalities. I dont want my bundle size to be more.
Here is my Code https://codesandbox.io/s/crud-using-react-table-6-rs2r9
Whenever I try to edit and change values using input, the table re-renders. I think the issue is because, the Cell inside the columns re-renders when I change the state. But I'm not able to get a workaround for this. Any help would be appreciated greatly. Thanks.
I did some experiments and found that, react-table-6 library doesn't support input element.
However with contentEditable div, It seems to work perfectly.
Code with Input
import React from "react";
import "./styles.css";
import ReactTable from "react-table-6";
import "react-table-6/react-table.css";
export default function App() {
const [state, setState] = React.useState({
data: [
{
name: "Adam",
age: 20
},
{
name: "Eve",
age: 19
},
{
name: "Abel",
age: 4
},
{
name: "Coin",
age: 5
}
],
edit: {}
});
return (
<ReactTable
data={state.data}
columns={[
{
Header: "Name",
accessor: "name",
Cell: ({ value, ...props }) =>
state.edit.name === props.original.name ? (
<input
value={state.edit.name}
onChange={(e) => {
console.log(e.target.value);
setState({
...state,
edit: { ...state.edit, name: e.target.value }
});
}}
/>
) : (
value
)
},
{
Header: "Age",
accessor: "age"
},
{
Cell: ({ value, ...props }) =>
Object.keys(state.edit).length > 0 &&
state.edit.name === props.original.name ? (
<button>Save</button>
) : (
<button
onClick={(e) => setState({ ...state, edit: props.original })}
>
Edit
</button>
)
}
]}
/>
);
}
Code with content editable div
import React from "react";
import "./styles.css";
import ReactTable from "react-table-6";
import "react-table-6/react-table.css";
export default function App() {
const [state, setState] = React.useState({
data: [
{ id: 1, name: "Adam", age: 20 },
{ id: 2, name: "Eve", age: 19 },
{ id: 3, name: "Abel", age: 4 },
{ id: 4, name: "Coin", age: 5 }
],
edit: {}
});
return (
<ReactTable
data={state.data}
columns={[
{
Header: "Name",
accessor: "name",
Cell: ({ value, ...props }) => (
<div
style={
state.edit.id === props.original.id
? {
backgroundColor: "#ddd",
padding: "5px",
outline: "1px solid #0000ff"
}
: {}
}
contentEditable={state.edit.id === props.original.id}
suppressContentEditableWarning
onBlur={(e) => {
setState({
...state,
edit: { ...state.edit, name: e.target.innerHTML }
});
}}
dangerouslySetInnerHTML={{
__html:
state.edit.id === props.original.id ? state.edit.name : value
}}
/>
)
},
{
Header: "Age",
accessor: "age"
},
{
Cell: ({ value, ...props }) =>
Object.keys(state.edit).length > 0 &&
state.edit.id === props.original.id ? (
<button
onClick={(e) => {
let newdata = state.data;
newdata.map((d) => {
if (d.id === state.edit.id) {
d.name = state.edit.name;
}
return d;
});
console.log(newdata);
setState({ ...state, data: newdata, edit: {} });
}}
>
Save
</button>
) : (
<button
onClick={(e) => setState({ ...state, edit: props.original })}
>
Edit
</button>
)
}
]}
defaultPageSize={5}
/>
);
}

Categories

Resources