Ant design Transform component extracting selected data - reactjs

I need to extract selected/filtered data into the state. I tried everything with onChange and on select change but only I got is the ID of one specific item.
ex. extracted_data = [ '1','2','3'....]
But I need a complete Item with id, name, price, etc...
I am passing data as source data, and after selecting I want to send in the parent component because I need to send it on the server.
Code is below
import { Table, Transfer } from "antd";
import difference from "lodash/difference";
import React, { useState } from "react";
// Customize Table Transfer
const TableTransfer = ({ leftColumns, rightColumns, ...restProps }) => (
<Transfer {...restProps}>
{({
direction,
filteredItems,
onItemSelectAll,
onItemSelect,
selectedKeys: listSelectedKeys,
disabled: listDisabled,
}) => {
const columns = direction === "left" ? leftColumns : rightColumns;
const rowSelection = {
getCheckboxProps: (item) => ({
disabled: listDisabled || item.disabled,
}),
onSelectAll(selected, selectedRows) {
const treeSelectedKeys = selectedRows
.filter((item) => !item.disabled)
.map(({ key }) => key);
const diffKeys = selected
? difference(treeSelectedKeys, listSelectedKeys)
: difference(listSelectedKeys, treeSelectedKeys);
onItemSelectAll(diffKeys, selected);
},
onSelect({ key }, selected) {
onItemSelect(key, selected);
},
selectedRowKeys: listSelectedKeys,
};
return (
<Table
rowSelection={rowSelection}
columns={columns}
dataSource={filteredItems}
size="small"
style={{
pointerEvents: listDisabled ? "none" : undefined,
}}
onRow={({ key, disabled: itemDisabled }) => ({
onClick: () => {
if (itemDisabled || listDisabled) return;
onItemSelect(key, !listSelectedKeys.includes(key));
},
})}
/>
);
}}
</Transfer>
);
const leftTableColumns = [
{
dataIndex: "name",
title: "Name",
},
{
dataIndex: "price",
title: "Price (€)",
},
{
dataIndex: "discount",
title: "Discount (%)",
},
];
const rightTableColumns = [
{
dataIndex: "name",
title: "Name",
},
{
dataIndex: "price",
title: "Price",
},
];
const App = ({ data, func }) => {
const mockData = data.map((item) => ({
key: item.id.toString(),
name: item.name,
price: item.price,
discount: item.discount,
}));
const originTargetKeys = mockData.map((item) => item.key);
const [targetKeys, setTargetKeys] = useState(originTargetKeys);
const [selected, setSelected] = useState([]);
const onSelectChange = (e) => {
setSelected(e);
};
const onChange = (e) => {
setTargetKeys(e);
func(selected);
};
return (
<>
<TableTransfer
dataSource={mockData}
targetKeys={targetKeys}
disabled={false}
showSearch={true}
onChange={onChange}
onSelectChange={onSelectChange}
filterOption={(inputValue, item) =>
item.name.indexOf(inputValue) !== -1
}
leftColumns={leftTableColumns}
rightColumns={rightTableColumns}
/>
</>
);
};
export default App;

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 can I have a button in a const object?

I'm learning React.js and this is a table showing which user has which items.
I would like to have a button for each item and delete the corresponding item.
How do you have or {FaTrash} icon in a const object?
This is my full code below
const columns = [
{
name: "Username",
selector: "username",
sortable: true
},
{
name: "Email",
selector: "email",
sortable: true
},
{
name: "Item",
selector: "items",
sortable: true,
right: true
},
{
name: "Action",
value: <button>Edit</button>
}
]
const Admin = () => {
const [data, setData] = useState(allUsers);
const handleRowClicked = row => {
const updatedData = data.map(item => {
if (row.id !== item.id) {
return item;
}
return {
...item,
toggleSelected: !item.toggleSelected
};
});
setData(updatedData);
}
return ( <>
<div className='users p-5'>
<DataTable
title="Users"
columns={columns}
data={data}
defaultSortField="title"
pagination
onRowClicked={handleRowClicked}
/>
</div>
</> );
}
export default Admin;
I used to pass a function that returns a piece of layout with handler
{
name: "Action",
actionRenderer: ({ index, item }) => {
return (
<button onClick={() => onhandle(item)}>
ActionName <!--or icon component-->
</button>
)
}
},
Than you need to create <DataTableRow> component wich will render each object in your columns array. Somewhere in the <DataTableRow> you will be able to access to actionRenderer and your data item:
<div>{actionColumn.actionRenderer({ index, item })}</div>

React Card Example issue - Card is replaced instead of being appended to a list of cards in another column

I have been persistently working on this problem where the goal is to drag a card form 'Column 1' and copy that into another column say 'Column 2'.
Now when my first card is dragged and drop it into 'Column 2, the card is accordingly added to that column, but when I drag another card and drop into 'Column 2' instead of being appended it just replaces the existing card with itself.
I have been debugging the state, but the issue still persists. I haven't gotten a clue what am I doing wrong here?
Here's my code
// Card Component
function Card({ id, text, isDrag }) {
const [, drag] = useDrag(() => ({
type: "bp-card",
item: () => {
return { id, text}
},
collect: monitor => ({
isDragging: !!monitor.isDragging(),
}),
canDrag: () => isDrag
}));
return (
<div
className='card'
ref={drag}
style={{
cursor: isDrag ? 'pointer' : 'no-drop'
}}
>
{text}
</div>
)
}
// Column Component
function Column({ title, children, onCardDropped }) {
const [, drop] = useDrop(() => ({
accept: "bp-card",
drop: item => {
onCardDropped(item);
}
}));
return (
<div className="flex-item" ref={title === 'Column 2' ? drop : null}>
<p>{title}</p>
{children.length > 0 && children.map(({ id, text, isDrag }) => (
<Card
key={id}
id={id}
text={text}
isDrag={isDrag}
/>
))}
</div>
)
}
// Main App
function App() {
const [cards] = useState([
{ id: 1, text: 'Card 1', isDrag: true },
{ id: 2, text: 'Card 2', isDrag: true },
]);
const [columns, setColumns] = useState([
{
id: 1,
title: 'Column 1',
children: cards
},
{
id: 2,
title: 'Column 2',
children: []
},
]);
const onCardDropped = ({ id, text }) => {
// let card = null;
const targetColumnId = 2;
const transformedColumns = columns.map(column => {
if (column.id === targetColumnId) {
return {
...column,
children: [
...column.children,
{ id, text }
]
}
}
return column;
});
setColumns(transformedColumns);
}
return (
<DndProvider backend={HTML5Backend}>
<div className='flex-container'>
{columns.map((column) => (
<Column
key={column.id}
title={column.title}
children={column.children}
onCardDropped={onCardDropped}
/>
))}
</div>
</DndProvider>
);
}
Any help is highly appreciated. Thanks.
You need to consider the previous state using the callback of the set state method. It starts to work after changing the onCardDropped as below.
const onCardDropped = ({ id, text }) => {
// let card = null;
const targetColumnId = 2;
setColumns((prevColumns) =>
prevColumns.map((column) => {
if (column.id === targetColumnId) {
return {
...column,
children: [...column.children, { id, text }]
};
}
return column;
})
);
};
It's always a good idea to use the state from the callback method as opposed to using the state object directly which might be stale.
Working 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.

fluent ui details List implementation in Functional component

Can anybody send code on how to implement fluent UI details List in Functional Component(https://developer.microsoft.com/en-us/fluentui#/controls/web/detailslist/basic) and how to fetch data from API to details List
That's a start you will need to "refact" this code by the way this is a really good practice :
import * as React from "react";
import { Announced } from "office-ui-fabric-react/lib/Announced";
import {
TextField,
ITextFieldStyles
} from "office-ui-fabric-react/lib/TextField";
import {
DetailsList,
DetailsListLayoutMode,
Selection,
IColumn
} from "office-ui-fabric-react/lib/DetailsList";
import { MarqueeSelection } from "office-ui-fabric-react/lib/MarqueeSelection";
import { Fabric } from "office-ui-fabric-react/lib/Fabric";
import { mergeStyles } from "office-ui-fabric-react/lib/Styling";
import { Text } from "office-ui-fabric-react/lib/Text";
const exampleChildClass = mergeStyles({
display: "block",
marginBottom: "10px"
});
const textFieldStyles: Partial<ITextFieldStyles> = {
root: { maxWidth: "300px" }
};
export interface IDetailsListBasicExampleItem {
key: number;
name: string;
value: number;
}
export interface IDetailsListBasicExampleState {
items: IDetailsListBasicExampleItem[];
selectionDetails: string;
}
export const DetailsListBasicExampleFunction: React.FunctionComponent<
{} | IDetailsListBasicExampleState
> = () => {
const _allItems: IDetailsListBasicExampleItem[] = [];
const [selection, setSelection] = React.useState<Selection | undefined>();
function _getSelectionDetails(): string {
const selectionCount = selection ? selection.getSelectedCount() : 0;
switch (selectionCount) {
case 0:
return "No items selected";
case 1:
return (
"1 item selected: " +
(selection.getSelection()[0] as IDetailsListBasicExampleItem).name
);
default:
return `${selectionCount} items selected`;
}
}
const [state, setState] = React.useState({
items: _allItems,
selectionDetails: _getSelectionDetails()
});
React.useEffect(() => {
const _selection: Selection = new Selection({
onSelectionChanged: () =>
setState((prev) => {
return { ...prev, selectionDetails: _getSelectionDetails() };
})
});
setSelection(_selection);
for (let i = 0; i < 200; i++) {
_allItems.push({
key: i,
name: "Item " + i,
value: i
});
}
setState((prev) => {
return { ...prev, items: _allItems };
});
}, []);
const _columns: IColumn[] = [
{
key: "column1",
name: "Name",
fieldName: "name",
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: "column2",
name: "Value",
fieldName: "value",
minWidth: 100,
maxWidth: 200,
isResizable: true
}
];
// Populate with items for demos.
const _onFilter = (
ev: React.FormEvent<HTMLInputElement | HTMLTextAreaElement>,
text: string
): void => {
console.log(text);
setState((prev) => {
return {
...prev,
items: text
? _allItems.filter((i) => i.name.toLowerCase().indexOf(text) > -1)
: _allItems
};
});
};
const _onItemInvoked = (item: IDetailsListBasicExampleItem): void => {
alert(`Item invoked: ${item.name}`);
};
return selection ? (
<Fabric>
<div className={exampleChildClass}>{state.selectionDetails}</div>
<Text>
Note: While focusing a row, pressing enter or double clicking will
execute onItemInvoked, which in this example will show an alert.
</Text>
<Announced message={state.selectionDetails} />
<TextField
className={exampleChildClass}
label="Filter by name:"
onChange={(e, t) => _onFilter(e, t ?? "")}
styles={textFieldStyles}
/>
<Announced
message={`Number of items after filter applied: ${state.items.length}.`}
/>
<MarqueeSelection selection={selection}>
<DetailsList
items={state.items}
columns={_columns}
setKey="set"
layoutMode={DetailsListLayoutMode.justified}
selection={selection}
selectionPreservedOnEmptyClick={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="select row"
onItemInvoked={_onItemInvoked}
/>
</MarqueeSelection>
</Fabric>
) : (
<div>Loading</div>
);
};
UPDATE
To pass this sample of code in JSX this is pretty easy you just need to remove all type thing.
And to fetch data I use axios.
see the code below:
import * as React from "react";
import { Announced } from "office-ui-fabric-react/lib/Announced";
import { TextField } from "office-ui-fabric-react/lib/TextField";
import {
DetailsList,
DetailsListLayoutMode,
Selection
} from "office-ui-fabric-react/lib/DetailsList";
import { MarqueeSelection } from "office-ui-fabric-react/lib/MarqueeSelection";
import { Fabric } from "office-ui-fabric-react/lib/Fabric";
import { mergeStyles } from "office-ui-fabric-react/lib/Styling";
import { Text } from "office-ui-fabric-react/lib/Text";
import axios from "axios";
const exampleChildClass = mergeStyles({
display: "block",
marginBottom: "10px"
});
const textFieldStyles = {
root: { maxWidth: "300px" }
};
export const DetailsListBasicExampleFunction = () => {
const _allItems = [];
const [selection, setSelection] = React.useState();
function _getSelectionDetails() {
const selectionCount = selection ? selection.getSelectedCount() : 0;
switch (selectionCount) {
case 0:
return "No items selected";
case 1:
return "1 item selected: " + selection.getSelection()[0].name;
default:
return `${selectionCount} items selected`;
}
}
const [state, setState] = React.useState({
items: _allItems,
selectionDetails: _getSelectionDetails()
});
React.useEffect(() => {
const _selection = new Selection({
onSelectionChanged: () =>
setState((prev) => {
return { ...prev, selectionDetails: _getSelectionDetails() };
})
});
setSelection(_selection);
//********************** */fetch data from api***************************************
axios
.get("/data.json") //pass your url in param
.then((res) =>
setState((prev) => {
return { ...prev, items: res.data };
})
); //pass data in setState
}, []);
const _columns = [
{
key: "column1",
name: "Name",
fieldName: "name",
minWidth: 100,
maxWidth: 200,
isResizable: true
},
{
key: "column2",
name: "Value",
fieldName: "value",
minWidth: 100,
maxWidth: 200,
isResizable: true
}
];
// Populate with items for demos.
const _onFilter = (ev, text) => {
console.log(text);
setState((prev) => {
return {
...prev,
items: text
? _allItems.filter((i) => i.name.toLowerCase().indexOf(text) > -1)
: _allItems
};
});
};
const _onItemInvoked = (item) => {
alert(`Item invoked: ${item.name}`);
};
return selection ? (
<Fabric>
<div className={exampleChildClass}>{state.selectionDetails}</div>
<Text>
Note: While focusing a row, pressing enter or double clicking will
execute onItemInvoked, which in this example will show an alert.
</Text>
<Announced message={state.selectionDetails} />
<TextField
className={exampleChildClass}
label="Filter by name:"
onChange={(e, t) => _onFilter(e, t ?? "")}
styles={textFieldStyles}
/>
<Announced
message={`Number of items after filter applied: ${state.items.length}.`}
/>
<MarqueeSelection selection={selection}>
<DetailsList
items={state.items}
columns={_columns}
setKey="set"
layoutMode={DetailsListLayoutMode.justified}
selection={selection}
selectionPreservedOnEmptyClick={true}
ariaLabelForSelectionColumn="Toggle selection"
ariaLabelForSelectAllCheckbox="Toggle selection for all items"
checkButtonAriaLabel="select row"
onItemInvoked={_onItemInvoked}
/>
</MarqueeSelection>
</Fabric>
) : (
<div>Loading</div>
);
};

Resources