Display data in antd table based on selected item from select option - reactjs

I need to display data on the antd table based on the selected item from select option.The data that are to be displayed are stored in different variables. For example, if school is selected from select option then the datasource is available in schoolData and similarly for other option.
Here's my code:
import React, { useState } from "react";
import Framework from "../framework/Framework";
import { Dropdown, Button, Table, message, Select } from "antd";
import { DeleteOutlined, DownOutlined, EditOutlined } from "#ant-design/icons";
import { Content } from "antd/lib/layout/layout";
import AddNewButton from "../addNewButton/AddNewButton";
import "./attributes.css";
import DataSource from "./Datasource";
import IconDescription from "../icondescription/IconDescription";
import Modal from "antd/lib/modal/Modal";
import { Option } from "antd/lib/mentions";
const Attributes = () => {
const [page, setPage] = useState(1);
const [isModalVisible, setIsModalVisible] = useState(false)
// const [layer, setLayer] = useState()
const columns = [
{
title: "S.N",
dataIndex: "key",
},
{
title: "Name",
dataIndex: "name",
key: "name",
// render: (text) => <a>{text}</a>,
},
{
title: "Address",
dataIndex: "address",
key: "address",
},
{
title: "Contact No.",
dataIndex: "contactno",
key: "contactno",
},
{
title: "Operation",
dataIndex: "operation",
key: "operation",
render: () => {
return (
<div style={{ display: "flex" }}>
<IconDescription icon={<EditOutlined />} label="Edit" />
<IconDescription icon={<DeleteOutlined />} label="Delete" />
</div>
);
},
},
];
const addAttribute = () => {
setIsModalVisible(true)
}
const modalHandleOk = () => {
setIsModalVisible(false);
};
const modalHandleCancel = () => {
setIsModalVisible(false);
};
const selectLayer = (e) => {
console.log("select layer", e)
}
return (
<Framework>
<Content className="attributes">
<div className="select-addNewBtn-container">
<Select defaultValue="school" style={{ width: 120 }} onChange={selectLayer}>
<Option value="school">School</Option>
<Option value="hospital">Hospital</Option>
<Option value="policeStation">Police Station</Option>
</Select>
<AddNewButton name={"Add New Attribute"} addNewBtn={addAttribute} />
<Modal title={"Add New Attribute"} visible={isModalVisible} centered onCancel={modalHandleCancel} onOk={modalHandleOk}>
</Modal>
</div>
<Table
dataSource={DataSource}
columns={columns}
className="data-table"
pagination={{
size: "small",
pageSize: 6,
hideOnSinglePage: true,
showSizeChanger: false,
}}
/>
</Content>
</Framework>
);
};
export default Attributes;
How do i achieve the desired functionality? Do let me know. Quite a beginner at such things.

Assuming Datasource is just a simple array of data objects, and presumably you have another file eg: 'SchoolData' that you need to switch between when the select option is chosen.
What I'd do to keep it simple is create a react state variable to wrap your data and just set it at will in the onChange of your select.
Example

Related

ReactTable component is not rendering data coming from api,If i use hardcoded data it is showing

I am using reacttable-6 to render the data in table,but the is not showing up in table.It is giving me "No data found".Data is coming from api,even i console logged the response from api,the what data i am getting from is fine.I aslo hard coded the data,then the data is showing up in the table
I am not able to figure out what the issue is.Thanks inadvance.
import React,{useState} from 'react'
import ReactTable from "react-table-6";
import 'react-table-6/react-table.css';
import axios from "axios";
export default function Inventory(){
var compdata = [
{
FirstName: "Chandu",
LastName: "Reddy",
_id: "63c5766f9d9de1b624481574",
Discription: {
_id: "63c5766f9d9de1b624481574",
DOB: "Havells",
Age: "HiBreak",
},
Address: "Something",
}
];
const handleDelete=(data)=>{
console.log(data)
}
const handleEdit=()=>{
console.log("dcdc")
}
const column = [
{
Header: "FirstName",
accessor: "FirstName",
sortable: false
},
{
Header: "LastName",
accessor: "LastName",
sortable: false
},
{
Header: "Address",
accessor: "Address",
sortable: false
},
{
Header: "Actions",
Cell: (row) => (
<div>
<a onClick={() => handleEdit(row.original)}>
Edit
</a>
<a onClick={() => handleDelete(row.original)}>
Delete
</a>
</div>
)
}
];
const [data1, setData1] = useState([]);
const [columns, setColumns] = useState(column);
const { toggle } = useContext(ThemeContext);
useEffect(()=>{
const fetch = async () => {
await axios
.get(`http://localhost:4001/api/uploadCsv/getData`)
.then((res) => {
setData1(res.data);
console.log(res.data)
});
};
fetch();
},[setData1]);
const [expanded, setExpanded] = useState({});
const onExpandedChange = (newExpanded) => {
setExpanded(newExpanded);
};
return(
<div className="container">
<div className='Table-container'>
<ReactTable
data={data1}
columns={columns}
defaultPageSize={data1.length}
showPagination={false}
resizable={false}
expanded={expanded}
// className="-striped -highlight"
getTrProps={(state, rowInfo, column, instance, expanded) => {
return rowInfo
? {
onClick: (expanded) => {
const newExpanded = { ...expanded };
newExpanded[rowInfo.viewIndex] = expanded[rowInfo.viewIndex]
? false
: true;
setExpanded(newExpanded);
}
}
: {};
}}
SubComponent={(row) => {
return (
<div style={{ padding: "20px" }}>
<em>{(row.original.Discription.Make)}</em>K <br />
</div>
);
}}
/>
<br />
</div>
</div>
)
}
Screen shot for reference
Change your useEffect like this and add another to check did data1 updated yet. Depend on data1 have value or not we will have different way to solve this
useEffect(() => {
axios.get(`http://localhost:4001/api/uploadCsv/getData`).then((res) => {
setData1(res.data);
});
}, []);
useEffect(()=>{
console.log(data1)
},[data1])

How to pass state between renderCell components in MUI Data Grid

How can I change the MenuItems of one Select when another Select component changes using DataGrid? I need to be able to pass the state of one Select component to the other, but I'm not sure how when using renderCell.
For example, let's say I have the following object:
const data = {
"/path/to/file1.csv": {
parameters: ["Parameter 1", "Parameter 2", "Parameter 3"],
},
"/path/to/file2.csv": {
parameters: ["Parameter 2", "Parameter 3", "Parameter 4"],
},
"/path/to/file3.csv": {
parameters: ["Parameter 5", "Parameter 6", "Parameter 7"],
},
};
In my DataGrid table, every time I add a new row with the click of a button, the first cell has a Select component containing Object.keys(data).
The second cell contains another Select component. I want this Select component to contain parameters that are dependent on the value selected. For example, if /path/to/file1.csv is selected, I want to make available those parameters (Parameter 1, Parameter 2, Parameter 3), but if /path/to/file3.csv is selected, I want to make available those parameters (Parameter 5, Parameter 6, Parameter 7).
Here's my component:
import * as React from "react";
import PropTypes from "prop-types";
import { Button, Select, MenuItem } from "#mui/material";
import DeleteIcon from "#mui/icons-material/Delete";
import { DataGrid, GridActionsCellItem } from "#mui/x-data-grid";
const FileSelect = (props) => {
const { value } = props;
const [file, setFile] = React.useState("");
const handleChange = (event) => {
setFile(event.target.value);
};
return (
<Select id="file-select" value={file} onChange={handleChange} fullWidth>
{value?.map((item, index) => (
<MenuItem key={index} value={item}>
{item}
</MenuItem>
))}
</Select>
);
};
FileSelect.propTypes = {
value: PropTypes.array,
};
const ParameterSelect = (props) => {
const { value } = props;
const [parameter, setParameter] = React.useState("");
const handleChange = (event) => {
setParameter(event.target.value);
};
return (
<Select
id="parameter-select"
value={parameter}
onChange={handleChange}
fullWidth
>
{value?.map((item, index) => (
<MenuItem key={index} value={item}>
{item}
</MenuItem>
))}
</Select>
);
};
export default function DataGridTable(props) {
const { data } = props;
const files = Object.keys(data);
const [rows, setRows] = React.useState([]);
const columns = [
{
field: "file",
headerName: "File",
// width: 200,
flex: 1,
renderCell: FileSelect,
},
{
field: "x",
headerName: "X",
// width: 200,
flex: 0.5,
renderCell: ParameterSelect,
},
{
field: "actions",
headerName: "Delete",
type: "actions",
width: 80,
getActions: (params) => [
<GridActionsCellItem
icon={<DeleteIcon />}
label="Delete"
onClick={deleteRow(params.id)}
/>,
],
},
];
const handleClick = () => {
const newRow = {
id: rows.length + 1,
file: files,
x: [],
};
setRows((prevState) => [...prevState, newRow]);
};
const deleteRow = React.useCallback(
(id) => () => {
setTimeout(() => {
setRows((prevRows) => prevRows.filter((row) => row.id !== id));
});
},
[]
);
return (
<div>
<Button variant="contained" onClick={handleClick}>
Add row
</Button>
<div style={{ height: 300, width: "100%" }}>
<DataGrid rows={rows} columns={columns} disableSelectionOnClick />
</div>
</div>
);
}
The simplest way that I could think to accomplish this is by adding an extra field to the column definition as an "easy" place to store the selected value.
...
const FileSelect = (props) => {
const { value, row } = props;
const [file, setFile] = React.useState("");
const handleChange = (event) => {
setFile(event.target.value);
// Set the value here
row.selectedFile = event.target.value;
};
return (
<Select id="file-select" value={file} onChange={handleChange} fullWidth>
{value?.map((item, index) => (
<MenuItem key={index} value={item}>
{item}
</MenuItem>
))}
</Select>
);
};
...
{
field: "selectedFile",
hideable: true
},
...
Then set the selected value (file) in the FileSelect parent value in the selectedFile column. Then all that was left to do was to make the parameters lookup values available to the ParameterSelect. Again, I just stuffed them into the renderCell props, but this could be done better as well:
...
{
field: "x",
headerName: "X",
flex: 0.5,
// Passing the entire original data in as an extra param, for demonstration purposes
renderCell: (props) => ParameterSelect({ ...props, data })
},
...
Finally, just hide the selectedFile column:
...
<DataGrid
rows={rows}
columns={columns}
disableSelectionOnClick
// Hiding the extra field
columnVisibilityModel={{
selectedFile: false
}}
/>
...
Producing this: (I changed your values to make them easier to read while I was working)
Working CodeSandBox: https://codesandbox.io/s/prod-sun-bdvcu0?file=/demo.js:842-854

How to disable a specific row to be draggable in AG table?

I am using the Managed Dragging of AG Grid React table and want to disable a specific row, if it matches the condition.
In Docs I couldn't find enough information how to do that. As it describes here, it is possible to add the draggable feature conditionally, like this
rowDrag: params => !params.node.group
In params object, I couldn't find the row data to implement my condition.
In the code example described below, I want to disable the row to be draggable if the name==='John.
Also, how to that if you have row draggable for entire row: rowDragEntireRow={true}?
Sandbox demo and code
import React from "react";
import { AgGridReact } from "ag-grid-react";
import "ag-grid-community/dist/styles/ag-grid.css";
import "ag-grid-community/dist/styles/ag-theme-alpine.css";
function App() {
const [gridApi, setGridApi] = React.useState(null);
const [gridColumnApi, setGridColumnApi] = React.useState(null);
const onGridReady = (params) => {
setGridApi(params.api);
setGridColumnApi(params.columnApi);
};
const defaultColDef = {
flex: 1,
editable: true
};
const columnDefs = [
{
headerName: "Name",
field: "name",
rowDrag: (params) => {
console.log("params", params);
return !params.node.group;
}
},
{ headerName: "stop", field: "stop" },
{
headerName: "duration",
field: "duration"
}
];
const rowData = React.useMemo(
() => [
{
name: "John",
stop: 10,
duration: 5
},
{
name: "David",
stop: 15,
duration: 8
},
{
name: "Dan",
stop: 20,
duration: 6
}
],
[]
);
return (
<div>
<h1 align="center">React-App</h1>
<div>
<div className="ag-theme-alpine" style={{ height: "700px" }}>
<AgGridReact
columnDefs={columnDefs}
rowData={rowData}
defaultColDef={defaultColDef}
onGridReady={onGridReady}
rowDragManaged={true}
//rowDragEntireRow={true}
></AgGridReact>
</div>
</div>
</div>
);
}
export default App;
Any help will be appreciated
Update your rowDrag definition in the name column definition to the following:
rowDrag: (params) => {
if (params.data.name == "John") {
return false;
}
return true;
}
Demo.

React Filter and Map data for Datagrid returning no values

I suspect it is a syntax issue. When I use the same approach for instead of I do get the expected results. The data is coming from an endpoint through the import of getAssembly which is generated via await fetch and the results are being rendered as JSON before the data is imported.
The commented out code on line how I assume the commanded need to be executed and I get no error, but no data is rendered. The code on line 50 works fine but does not provide the filtering. I intend the use the value in the typeName variable once the filtering is working.
import { useState, useEffect } from "react";
import MenuItem from "#mui/material/MenuItem";
import Select from "#mui/material/Select";
import InputLabel from "#mui/material/InputLabel";
import ListItemText from "#mui/material/ListItemText";
import { DataGrid } from "#mui/x-data-grid";
import { getAssembly } from "./GetAssembly";
const columns = [
{ field: "id", headerName: "ID", width: 300 },
{ field: "status", headerName: "Status", width: 90 },
{ field: "atype", headerName: "AType", width: 80 },
{ field: "name", headerName: "Name", width: 350 },
{ field: "time", headerName: "Start Time", width: 150 },
{ field: "org", headerName: "Organization", width: 350 },
];
export default function SelectAssembly() {
const [typeName, setTypeName] = useState([""]);
// const [assemRows, setAssemRows] = useState([]);
const [state, setState] = useState({
assembly: [],
assembtypename: [],
unsignenList: [],
});
const handleTypeChange = (event) => {
const {
target: { value },
} = event;
setTypeName(value);
};
console.log(typeName);
useEffect(() => {
console.log("useEffect");
getAssembly().then((res) => {
setState((prevState) => ({ ...prevState, assembly: res.assemblies }));
});
}, []);
const typeSelection = [
...new Set(state.assembly.map((item) => item.assemblyType)),
];
//const assemList = state.assembly.filter(assem => assem === "batch").map(assem => {
const assemList = state.assembly.map((assem) => {
return {
id: assem.assemblyId,
status: assem.status,
atype: assem.assemblyType,
name: assem.name,
time: assem.timeStarted,
org: assem.organizationId,
asid: assem.referenceId,
pmap: assem.propertiesMap,
};
});
// const unsignedList = assemList.filter((str) => {
// //str can include or str can equal with === (return str.includes("import");)
// return str === "import";
// });
return (
<div>
<InputLabel sx={{ fontSize: 12 }}>Assembly Type</InputLabel>
<Select
label="Type"
value={typeName}
sx={{ height: 35, fontSize: 10 }}
fullWidth
focused
onChange={handleTypeChange}
>
{typeSelection.map((types) => {
return (
<MenuItem key={types.indexOf(types) > -1} value={types}>
<ListItemText primary={types} />
</MenuItem>
);
})}
</Select>
<br />
<br />
<DataGrid
density="compact"
hideFooterRowCount
rows={assemList}
// rows={unsignedList}
columns={columns}
pageSize={15}
rowsPerPageOptions={[15]}
/>
</div>
);
}
Thanks to Jim Ptak at Southwire for helping me see the problem. In the filter method I did not specify the particular element to filter on. Once the code was modified as follows:
const assemList = state.assembly.filter(assem => assem.assemblyType === "MO import").map(assem => {
//const assemList = state.assembly.map((assem) => {
return {
id: assem.assemblyId,
status: assem.status,
atype: assem.assemblyType,
name: assem.name,
time: assem.timeStarted,
org: assem.organizationId,
asid: assem.referenceId,
pmap: assem.propertiesMap,
};
});
the contents of the datagrid filters perfectly.

react nav link redirect on condition

I have two values at data index: isOnline (true and false). Right now <NavLink /> renders on both true and false, but I want to render only when value is false and not when it's true. Is there any possibility to do that?
I want to hide hyperlink if value is true. Hyperlink should only be rendered with false value. At the moment it gives me hyperlink on both true and false. But I want true value not to be linked with any other stuff but false value should be clickable.
import React, { useEffect, useState } from 'react';
import {
Tabs, Icon, Divider, Table, Button, Input, Row, Col,
} from 'antd';
import moment from 'moment';
import { NavLink, Redirect } from 'react-router-dom';
import { getAllLeads } from '../../shared/services/apiService';
import { isSuccess } from '../../shared/utils/jsHelper';
import routePaths from '../../shared/routePaths';
// rowSelection object indicates the need for row selection
const rowSelection = {
onChange: (selectedRowKeys, selectedRows) => {
console.log(`selectedRowKeys: ${selectedRowKeys}`, 'selectedRows: ', selectedRows);
},
getCheckboxProps: (record) => ({
disabled: record.name === 'Disabled User', // Column configuration not to be checked
name: record.name,
}),
};
const dateFormat = 'YYYY-MM-DD';
const Leads = () => {
const [leadList, setLeadList] = useState([]);
const columns = [
{
title: 'Sl no.',
dataIndex: 'name',
render: (name, record) =><span>{leadList.indexOf(record) + 1}</span>
},
{
title: 'Date',
dataIndex: 'createdAt',
},
{
title: 'Name',
dataIndex: 'name',
},
{
title: 'Phone number',
dataIndex: 'phone_number',
},
{
title: 'Email id',
dataIndex: 'email',
},
{
title: 'Type',
dataIndex: 'type',
},
{
title: 'Comment',
dataIndex: 'comment',
},
{
title: 'Property name',
dataIndex: 'propertyId.name',
//render: (name, row) => {row.propertyId ? (<NavLink to={`${routePaths.PROPERTY}/${row.propertyId._id}`}>{name}</NavLink>) : null},
},
{
title:'On-Line / Off-Line',
dataIndex: 'isOnline',
// render: (isOnline, row) => {
// if(!isOnline){
// <NavLink to={`${routePaths.LEADSFORM}/${row._id}`}>
// {isOnline}
// </NavLink>
// }else{null}
// }
render: (isOnline, row) => <NavLink to={`${routePaths.LEADSFORM}/${row._id}`}>{isOnline}</NavLink>,
}
];
const [loading, setLoading] = useState(false);
var tokenSession = localStorage.getItem('token');
if(tokenSession!='undefined' && tokenSession == null){
var setTokenSession = true;
}else{
var setTokenSession = false;
}
const [loggedDashOut, setDashLoggedOut] = useState(setTokenSession? true:false);
if (loggedDashOut) {
return <Redirect to={routePaths.LOGIN} />;
}
const getLeadsList = () => {
setLoading(true);
getAllLeads().then((resp) => {
if (isSuccess(resp)) {
setLeadList(resp.data.data);
}
}).finally(() => setLoading(false));
};
useEffect(() => {
getLeadsList();
return () => {};
}, []);
return (
<Row className="row-pad">
<Col xs={24} sm={24} md={8} lg={8} xl={8}><h3>Leads</h3></Col>
<Col xs={24} sm={24} md={8} lg={8} xl={8}></Col>
<Col xs={24} sm={24} md={8} lg={8} xl={8}>
<NavLink to={routePaths.LEADSFORM}>
<Button type="primary" className="btn-add">Add Leads</Button>
</NavLink>
</Col>
<Divider />
<Table pagination={{ pageSize: 10 }} columns={columns} dataSource={leadList} />
</Row>
);
};
export default Leads;
I'm not sure where is your isOnline variable, but basically if you want to render something conditionally you can try:
return (
...
{isOnline ? null : <NavLink />}
...
)
This will render the <NavLink /> component only when isOnline is false.
This is not the only way to implement conditional rendering in React, just a very common one, and I think it suits your use case.
For more details you can refer to the official docs regarding conditional rendering.
Good luck!

Resources