Custom Column Searching & Filtering in Material Table - javascript

I have a column in my table called Active. Data in this column is returned as 1 or 0 for Active and Inactive.
These values are not displayed as 1 or 0. Instead, using the render prop, I have a function generateFlagText which looks for the value and renders an MUI Chip component.
Users cannot search the column by typing Active or Inactive, they would have to type 1 or 0, but they don't know this.
How can I write a check for Active or Inactive to display only those rows in the table using the customSearchAndFilter prop in Material-Table?
This is my column and function:
{
title: <Typography className={classes.colHeader}>Active</Typography>,
field: "Active",
render: (rowData) => generateFlagText(rowData.Active),
// customFilterAndSearch: (term, rowData) => console.log(term), // term is the user input
},
...
export function generateFlagText(status) {
if (status === 1)
return (
<Chip
label={"Active"}
style={{
backgroundColor: "#D9F5FD",
border: "1px solid #5CC1EE",
borderRadius: "4px",
color: "#0063B8",
}}
/>
);
if (status === 0)
return (
<Chip
label={"Inactive"}
style={{
backgroundColor: "#FFEBF5",
border: "1px solid #F69AC6",
borderRadius: "4px",
color: "#A8396F",
}}
/>
);
}

You can make something like this
const data = { type: "active" };
const rows = [
{ name: 1, active: 1 },
{ name: 2, active: 0 }
];
function f(data, rows) {
const mappedValues = {
active: 1,
inactive: 0
};
const currFilter = [];
Object.keys(mappedValues).forEach((key) => {
if (key.includes(data.type)) {
currFilter.push(mappedValues[key]);
}
});
return rows.filter((row) =>
currFilter.some((filterValue) => filterValue === row.active)
);
}
console.log(f(data, rows));
User can input any text and function return rows which includes symbols from ui table.
But it would be easier to make not an input, but a selection of two values in a selector

Related

how to hide a row in mui data grid

I have a data grid using MUI. I want to hide a few rows and not display them based on a given condition and if a particular value exists in a column. How do I hide it? There seems to be props such as
hide
for columns but there is nothing for rows.
EDIT
The code is as follows
I want to hide the row from being displayed if a value exists in the 4th column (field: 'recvDistLocId')
and I want to hide the rows only when I press a button in the toolbar. So basically, its like a filter. Initially, all the data should be displayed and if I click the button, all rows with a value in the 4th column should disappear.
const columns = []
columns.push({
field: 'code',
headerName: nowrapHeader(appLanguages.serialCode[lang]),
flex: 1,
getApplyQuickFilterFn: getApplyFilterFnSameYear
});
columns.push({
field: 'brandId',
headerName: nowrapHeader(appLanguages.brand[lang]),
renderCell: (params) =>
getSelectCustomBodyRender(this.getBrandOptionMap(), params.row.brandId),
flex: 1,
});
columns.push({
field: 'slip',
headerName: nowrapHeader(appLanguages.slipNum[lang]),
renderCell: (params) => this.getSlipText(params.row.slip),
flex: 1,
});
columns.push({
field: 'recvDistLocId',
headerName: 'RecvDistLocId',
flex: 1,
hide: true,
});
/////This is the main data grid element code in the render()
<div style={{ height: 640, width: '100%' }}>
<DataGrid
sx={{
'& .MuiDataGrid-columnHeaderCheckbox .MuiDataGrid-columnHeaderTitleContainer': {
display: 'none',
},
}}
rows={serialsList || []}
columns={columns}
rowsPerPageOptions={[25, 50, 100]}
checkboxSelection={this.state.cancelShipFlag ? true : false}
disableSelectionOnClick={false}
components={{
Toolbar: NewToolbar,
}}
onSelectionModelChange={(ids) => {
const selectedIDs = new Set(ids);
const selectedRows = rowData.filter((row) => selectedIDs.has(row.id));
this.setState({ rowinfo: selectedRows });
this.setState({ selectedrows: ids });
//console.log('Selected rows: ' + this.state.selectedrows);
}}
selectionModel={this.state.selectedrows}
/>
</div>
filter the data based on the condition
// use setFilterValue to set the value of the clicked column e.g. recvDistLocId
const [filterValue, setFilterValue] = React.useState()
// assuming serialsList is array of strings
// use same case for comparing values
// use row.toLowerCase() !== filterValue.toLowerCase()
const rows = (serialsList || []).filter(row => row !== filterValue)
Then pass rows to the data grid
<DataGrid
rows={rows}
....

Merging rows in antd table if it has the same value

So I have an antd table in ReactJS that gets its data from an API call. So in my "account name" column, I have multiple values that are the same and I want to merge them into one row. I've tried looking for questions here and found this codesandbox project that does exactly what I want but when I applied it to my code, it wouldn't work. It drops the cells in my account name column and replaces it with values from the next column (Basically, moving my rows to the left and leaving the last column blank.)
UPDATE: I've added another sandbox link to recreate my problem or where I am at.
const names = new Set();
useEffect(() => {
names.clear();
});
const columns = [
{
key: "1",
title: "Account Name",
dataIndex: "account-name",
rowSpan: 1,
render: (value, row, index) => {
const obj = {
children: value,
props: {}
};
console.log(names.has(value), value);
if (names.has(value)) {
obj.props.rowSpan = 0;
} else {
const occurCount = dataSource.filter(data => data['account-name'] === value).length;
console.log(occurCount);
obj.props.rowSpan = occurCount;
names.add(value);
}
return obj;
},
sorter: (record1,record2) => record1['account-name'].localeCompare(record2['account-name']),
filterDropdown: ({ setSelectedKeys, selectedKeys, confirm }) => {
return (
<Input
autoFocus
placeholder="Search Column..."
value={selectedKeys[0]}
onChange={(e) => {
setSelectedKeys(e.target.value ? [e.target.value] : []);
}}
onPressEnter={() => {
confirm();
}}
onBlur={() => {
confirm();
}}
></Input>
);
},
filterIcon: () => {
return <SearchOutlined />;
},
onFilter: (value, record) => {
return record['account-name'].toLowerCase().includes(value.toLowerCase());
}
},
{
key:"2",
title:'Group ID',
dataIndex:'group-id',
sorter: (record1,record2) => record1['group-id'].localeCompare(record2['group-id']),
width: '18%',
rowSpan: 1,
},
{
key:"3",
title:'Financial Account ID',
dataIndex:'financial-account-id',
sorter: (record1,record2) => record1['financial-account-id'].localeCompare(record2['financial-account-id']),
width: '15%',
rowSpan: 1,
},
{
key:"4",
title:'Industry',
dataIndex:'industry',
sorter: (record1,record2) => record1.industry.localeCompare(record2.industry),
width: '15%',
rowSpan: 1,
},
{
key:"5",
title:'Billing Address',
dataIndex:'billing-address',
rowSpan: 1,
},
];
return (
<div>
<Table
bordered={true}
loading={loading}
columns={columns}
dataSource={dataSource}
pagination={true}
/>
</div>
)
}
When I change the value of obj.props.rowSpan into 0 it drops the whole columns of values. but when I change it into 1, it looks normal but without merging the rows.
Any help would be greatly appreciated I've been trying to fix this for a week.

Get row data from MuiDataTable

I am trying to get the row data from MuiDataTable but when I set the index from the onRowSelectionChange function to a state, my checkbox animation stops working, here is how my options look:
const options = {
resizableColumns: true,
draggableColumns: {
enabled: true,
},
onRowSelectionChange: (rowData: any) => {
let rowIndex = rowData.map((e: any) => e.dataIndex);
setState(rowIndex)
},
onRowSelectionChange : (curRowSelected, allRowsSelected) => {
console.log("All Selected: ", allRowsSelected);
},
This will collect only index and dataIndex values
const [selectedFabrics, setSelectedFabrics] = useState([])
customToolbarSelect: selectedRows => (
<IconButton
onClick={() => {
// console.log(selectedRows.data)
const indexesToPrint = selectedRows.data.map((row, k) => row.dataIndex);
let temp = [];
for (let i = 0; i < fabricList.length; i++) {
if (indexesToPrint.includes(i)) {
temp.push(fabricList[i]['id']);
}
}
setSelectedFabrics(temp);
}}
style={{
marginRight: "24px",
height: "48px",
top: "50%",
display: "block",
position: "relative",
transform: "translateY(-50%)",
}}
>
<span style={{marginTop: "23px"}}>Print QR Code</span>
</IconButton>
),
Here fabricList is my total table raw data. From selecting rows index we can filter with actual fabricList index and push raw data to a new state.
Also if you want to remove the delete icon from top during multiple rows select. use it.
customToolbarSelect: () => {},

React-data-table -Adding a CSS class to row dynamically

I am using an datatable of react-data-table-component, my table is generated from the API response data. I want to dynamically add a class to each of the rows generated based on the condition. How can I acheive this ?
https://www.npmjs.com/package/react-data-table-component
I am using the above datatable.
let columns= [
{
name: "ID",
selector: "ID",
sortable: true,
cell: row => <div>{row.ID}</div>
}];
<Datatable
columns={columns}
data={this.state.mydata} />
I want to add a custom CSS class to the entire row of this data table based on a condition.
I think you might be looking for the getTrProps callback in the table props:
getTrProps={ rowInfo => rowInfo.row.status ? 'green' : 'red' }
It's a callback to dynamically add classes or change style of a row element
Should work like this if I remember correctly:
getTrProps = (state, rowInfo, instance) => {
if (rowInfo) {
return {
className: (rowInfo.row.status == 'D') ? "status-refused" : "", // no effect
style: {
background: rowInfo.row.age > 20 ? 'red' : 'green'
}
}
}
return {};
}
render() {
<Datatable
columns={columns}
data={this.state.mydata}
getTrProps={this.getTrProps}
/>
}
example:
...
const conditionalRowStyles = [
{
when: row => row.calories < 300,
style: {
backgroundColor: 'green',
color: 'white',
'&:hover': {
cursor: 'pointer',
},
},
},
];
const MyTable = () => (
<DataTable
title="Desserts"
columns={columns}
data={data}
conditionalRowStyles={conditionalRowStyles}
/>
);
more info check here :) https://www.npmjs.com/package/react-data-table-component#conditional-row-styling

Highlight row in one react table is highlighting the same row in a second one on the page

I have two react tables on the same page with different data. I have the option for the user to select multiple rows in both tables. The problem I am experiencing, is that if they select any row in one table, it selects the same row in the other table. How do I make it so on select it only styles the table that was selected?
Here is the getTrProps for the first table.
<ReactTable
data={this.state.table1state}
columns={columnNames}
showPagination={false}
minRows={0}
getTrProps={(state, rowInfo) => {
if (rowInfo && rowInfo.row) {
return {
onClick: (e) => {
if (this.state.selectedOpp.indexOf(rowInfo.index) >= 0) {
var selectedOpp = this.state.selectedOpp;
selectedOpp.splice(selectedOpp.indexOf(rowInfo.index), 1);
this.setState({ selectedOpp: selectedOpp });
} else {
var selectedOpp = this.state.selected;
selectedOpp.push(rowInfo.index);
this.setState({ selectedOpp: selectedOpp });
}
},
style: {
background: this.state.selectedOpp.indexOf(rowInfo.index) >= 0 ? '#00afec' : 'white',
color: this.state.selectedOpp.indexOf(rowInfo.index) >= 0 ? 'white' : 'black'
}
}
} else {
return {}
}
}}
/>
And here is for the second. Exactly the same except I am using a different state to store the selected rows in, which doesn't fix the problem.
<ReactTable
data={this.state.table2state}
columns={columnNames}
showPagination={false}
minRows={0}
getTrProps={(state, rowInfo) => {
if (rowInfo && rowInfo.row) {
return {
onClick: (e) => {
if (this.state.selected.indexOf(rowInfo.index) >= 0) {
var selected = this.state.selected;
selected.splice(selected.indexOf(rowInfo.index), 1);
this.setState({ selected: selected });
} else {
var selected = this.state.selected;
selected.push(rowInfo.index);
this.setState({ selected: selected });
}
},
style: {
background: this.state.selected.indexOf(rowInfo.index) >= 0 ? '#00afec' : 'white',
color: this.state.selected.indexOf(rowInfo.index) >= 0 ? 'white' : 'black'
}
}
} else {
return {}
}
}}
/>
Any way to specify more, like only style this specific table that this row is part of rather than that row index of all tables?
Thanks.
They are mapped to the same state of their container component. You might be passing different state variables for data but the selected state variable is the same for both React tables and so with the context being bound in the arrow functions, it's using the same parent state variable selected.
Try having different selected arrays for both the React tables.
Also, reduce code redundancy
<ReactTable
key="table1"
data={this.state.table2state}
columns={columnNames}
showPagination={false}
minRows={0}
getTrProps={(state, rowInfo) => {
const selected = this.state.selectedTable1;
if (rowInfo && rowInfo.row) {
return {
onClick: (e) => {
if (this.state.selectedTable1.indexOf(rowInfo.index) >= 0) {
selected.splice(selected.indexOf(rowInfo.index), 1);
} else {
selected.push(rowInfo.index);
}
this.setState({ selectedTable1: selected });
},
style: {
background: this.state.selectedTable1.indexOf(rowInfo.index) >= 0 ? '#00afec' : 'white',
color: this.state.selectedTable1.indexOf(rowInfo.index) >= 0 ? 'white' : 'black'
}
}
} else {
return {}
}
}
}
/>
Ended up fixing this by not using the row index (rowInfo.index). Since the indexes are shared between tables, seemed to highlight both. So, instead I used the _id of the row data as follows:
<ReactTable
data={this.state.table2state}
columns={columnNames}
showPagination={false}
minRows={0}
getTrProps={(state, rowInfo) => {
if (rowInfo && rowInfo.row) {
return {
onClick: (e) => {
if (this.state.selected.indexOf(rowInfo.original._id) >= 0) {
var selected = this.state.selected;
selected.splice(selected.indexOf(rowInfo.original._id), 1);
this.setState({ selected: selected });
} else {
var selected = this.state.selected;
selected.push(rowInfo.original._id);
this.setState({ selected: selected });
}
},
style: {
background: this.state.selected.indexOf(rowInfo.original._id) >= 0 ? '#00afec' : 'white',
color: this.state.selected.indexOf(rowInfo.original._id) >= 0 ? 'white' : 'black'
}
}
} else {
return {}
}
}}
/>
This way each selection array has the id of the data in the row instead of just which row it is. Idk if you even need multiple selection arrays, prob dont, but still prob good to have them.

Categories