How can I add a drag icon on hover for rows in a table using react-table v7? The desired functionality is similar to the attached image. Can you provide some guidance or code examples to accomplish this?
image
Right now I have designed the rows(Here is the image of my current progressMy progress) but I am not able to find the logic how can I add the drag icon after row? Please help
<tr
{...row.getRowProps()}
ref={dropRef}
style={{ opacity, backgroundColor: 'white' }}
>
{/* {dragRow ? (
<DataTableBodyCell
ref={dragRef}
// noBorder={noEndBorder && rows.length - 1 === index}
align={'left'}
beforeColor="#6FF09C"
>
<DragIndicatorIcon
sx={{ fontSize: 80, width: '25px', height: '25px' }}
size="large"
/>
</DataTableBodyCell>
) : null} */}
{row.cells.map((cell) => (
<>
<DataTableBodyCell
noBorder={noEndBorder && data.length - 1 === index}
align={cell.column.align ? cell.column.align : 'left'}
cursor={handleRowStyle?.cursorStyle}
backgroundColor={handleRowStyle?.backgroundColor}
{...cell.getCellProps()}
beforeColor={cell?.row?.original?.isUsed?"#ffb100":"#6FF09C"}
cell={cell}
>
{cell.render('Cell')}
</DataTableBodyCell>
</>
))}
</tr>
This is how the row is rendered, I need to find out that How can I add drag icon outside the row and still I can drag and drop rows.
Related
Here is the code and the output it's pretty self-explanatory: I am trying to build a responsive layout and for some reason the button group will bleed out of the container and even get bigger when the screen size decreases.
<Container className="container">
<Grid container>
<Grid item xs={12} md={12} lg={6}>
<Chessboard
position={tour.fen}
isDraggablePiece={isDraggable}
onPieceDrop={onDrop}
customArrows={arrows}
onSquareClick={dropPiece}
onMouseOverSquare={mouseOver}
onMouseOutSquare={mouseOut}
customSquareStyles={{ ...options }}
customBoardStyle={{
borderRadius: "4px",
boxShadow: "0 5px 15px rgba(0, 0, 0, 0.5)",
}}
customDarkSquareStyle={{ background: "#90a2ad" }}
customLightSquareStyle={{ background: "#dfe3e6" }}
/>
<ButtonGroup variant="contained" className="controls">
{isFirst ? (
<Button onClick={randomStart}>Random Start</Button>
) : null}
{tour.visited.length !== 0 ? (
<Button
disabled={tour.completed !== null}
onClick={finishTour}
>
Complete Tour
</Button>
) : null}
{tour.completed !== null ? (
<Button onClick={visualiseComplete}>
Visualise
</Button>
) : null}
{tour.visited.length !== 0 ? (
<Button
onClick={() =>
setArrows(genArrows(tour.visitedStr))
}
>
Show path
</Button>
) : null}
{tour.visited.length !== 0 ? (
<Button onClick={undo}>Undo</Button>
) : null}
{tour.visited.length !== 0 ? (
<Button onClick={reset}>Reset</Button>
) : null}
</ButtonGroup>
</Grid>
<Grid item xs={12} md={12} lg={6}>
<Moves tour={tour} />
</Grid>
</Grid>
{/* <CompletedPanel tour={tour} impossible={impossible} /> */}
</Container>
Desktop version
Mobile version
I expect the the button group to fit inside the container and become stacked vertically
Perhaps make a responsive size value with useTheme and useMediaQuery from Material UI, and try with one or more of the following approaches.
Simplified live demo: stackblitz
Import the helper hooks:
import { useTheme } from '#mui/material/styles';
import useMediaQuery from '#mui/material/useMediaQuery';
In the component, create responsive condition:
const theme = useTheme();
// 👇 Customize this with preferred breakpoints
const matches = useMediaQuery(theme.breakpoints.up('sm'));
In the output, try one or more of these approaches for responsive values:
<ButtonGroup
// 👇 Make size based on responsive value
size={matches ? "medium" : "small"}
variant="contained"
aria-label="outlined primary button group"
// 👇 Define maxWidth for the group
sx={{ maxWidth: "100%" }}
// 👇 Conditional shorter text
>
<Button>{`${matches ? "complete " : ""}tour`}</Button>
<Button>{`${matches ? "show " : ""}path`}</Button>
<Button>undo</Button>
<Button>reset</Button>
</ButtonGroup>
As an alternative option, perhaps also consider to make the ButtonGroup layout horizontal when in smaller screen size:
<ButtonGroup
size={matches ? "medium" : "small"}
// 👇 Conditional orientation
orientation={matches ? "horizontal" : "vertical"}
variant="contained"
aria-label="outlined primary button group"
sx={{ maxWidth: "100%" }}
>
<Button>complete tour</Button>
<Button>show path</Button>
<Button>undo</Button>
<Button>reset</Button>
</ButtonGroup>
So I created a large list and I can get it to display and all that, but I need it to be editable....
so far I've tried:
putting in an html input tag, which does display but I can't even get the cursor to show in the field when clicking on it.
putting in a TextField element from material-ui... same thing can't edit it, though it does show
I'm not sure if editable fields or even buttons are possible within react-virtualized. Would anybody know? Two images are below of what it looks like now, and what I need it to look and function like
Here is the react-virtualized code
<div style={{ width: "100%", height: "100vh" }}>
<AutoSizer>
{({ width, height }) => (
<List
width={width}
height={height}
rowHeight={cache.current.rowHeight}
deferredMeasurementCache={cache.current}
rowCount={downloadedData.length}
rowRenderer={({ key, index, style, parent }) => {
const translation = downloadedData[index];
return (
<Table
width={width}
height={height}
headerHeight={20}
rowHeight={90}
rowCount={downloadedData.length}
rowGetter={({ index }) => downloadedData[index]}
>
<Column
dataKey="key"
label="Key"
width={.5 * width}
style={{ backgroundColor: 'red', display: 'none ' }}
/>
<Column
dataKey="value"
label="Value"
width={.5 * width}
style={{ backgroundColor: 'blue' }}
/>
</Table>
);
}}
/>
)}
</AutoSizer>
</div>
What it looks like
What I need it to look like
The default is [+] and [-].
and i want to increase this button size.
but i can't find the way in antd v.3.6.x...
Could not find a way to change it for more big size?
Thank you!!!
For antd version 3.6.x (for v3.1.x)
You can customize the css class .ant-table-row-expand-icon
.ant-table-row-expand-icon{
height: 25px;
width: 25px;
font-size: 30px;
}
Screenshot
For antd version 4.x
You can use expandIcon property to resize or change the icon, increase the fontSize to increase size of the icon
<Table
columns={columns}
expandable={{
expandedRowRender: (record) => (
<p style={{ margin: 0 }}>{record.description}</p>
),
rowExpandable: (record) => record.name !== 'Not Expandable',
expandIcon: ({ expanded, onExpand, record }) =>
expanded ? (
<MinusOutlined
style={{ fontSize: '20px' }}
onClick={(e) => onExpand(record, e)}
/>
) : (
<PlusOutlined
style={{ fontSize: '20px' }}
onClick={(e) => onExpand(record, e)}
/>
),
}}
dataSource={data}
/>
Screenshot
Antd Version < V4.x, you have to change the antd css directly.
Antd Version > V4.x. You can refer to the Ant Desing Doc codepen and style the expandIcon you want.
<Table
columns={columns}
dataSource={data}
expandable={{
expandedRowRender: record => (
<p style={{ margin: 0 }}>{record.description}</p>
),
expandIcon: ({ expanded, onExpand, record }) =>
expanded ? (
<MinusCircleTwoTone style={{ fontSize: "150%"}} onClick={e => onExpand(record, e)} />
) : (
<PlusCircleTwoTone style={{ fontSize: "150%"}} onClick={e => onExpand(record, e)} />
)
}}
codepen: https://codesandbox.io/s/fervent-bird-nuzpr?file=/index.js:1270-1684
I have a React JS app using Material-UI Table component that looks like this:
I need to change the style of the border between the last row of the same date and the first row of another date like between Date A and Date B like this:
My code to create the table is just a normal map :
<TableCell>
<Typography style={{ fontSize: 16 }}>{new Date(row.date).toLocaleDateString().slice(0, 10)}</Typography>
</TableCell>
<TableCell><Typography noWrap={true} style={{ fontSize: 16 }}>{row.user}</Typography></TableCell>
<TableCell><Typography style={{ fontSize: 16 }}>{row.duration}h</Typography></TableCell>
<TableCell><Typography style={{ fontSize: 16 }}>{row.description}</Typography></TableCell>
<TableCell style={{ width: 35 }} align="left">
<IconButton
className={classes.iconButton}
style={{ marginRight: 3 }}
onClick={() => openWorklogModalForEdit(row.id, row.date, row.duration, row.description, row.project_id, row.user_id, row.project, row.clientName)}>
<EditIcon className={classes.actionsButtonIcon} />
</IconButton>
</TableCell>
<TableCell style={{ width: 65 }} align="right" >
<IconButton
className={classes.iconButton}
onClick={() => deleteWorklog(row.id)}>
<DeleteIcon className={classes.actionsButtonIcon} />
</IconButton>
</TableCell>
</TableRow>
Thank you for your time!
You can add class for first table row of different date when using .map. Please refer to this code snippet for a simple demo.
Thoughts:
As you're using map to construct a table from an array, the syntax is
let newArray = arr.map(callback(currentValue[, index[, array]]) {
// return element for newArray, after executing something
}[, thisArg]);
docs: link
Then in the map callback body, you have access to current value and index. Then you can check whether the current item is the first of a new 'group', or a new date. If true, you can add a custom class to this row (as the demo is doing).
Then you can use css to add the border, so that you can achieve 'conditional styling based on previous value'.
If you can change the styling by adding or deleting class on some element this can easily be done.
<td className={shouldBeBlack ? 'black' : 'orange'} ></td>
so like depending on value of shouldBeBlack you can set css property of the table data or any element. Just depends how u r styling.
If there is some prop you can pass to the material ui element then same c=kind of ternary equation can be made for the same.
By apply mapping, you can add check like this
rows.map((row,index)=>{
if(index !== 0)?
<td className={row.date === rows[index-1].date? 'blackLine' : 'orangeLine'} </td>
:
<td className='black'} ></td>
})
I have the following code:
{item && item.description && (
<Link
style={{ display: 'block', paddingBottom: '2px' }}
title="View Details"
onClick={() => setIsOpen(!isOpen)}
{...aria}
>
View Details
<Icon icon={isOpen ? 'collapse_arrow' : 'expand_arrow'}
marginLeft="5px"
verticalAlign="bottom"
/>
</Link>
)}
The problem is that item.description could be an empty tag and therefore the condition is met and a Link component is rendered when it actually shouldn't be.
How is the best way I could avoid this case?
Thanks in advance!
You could use a regex to check for empty tags.
function checkForEmptyTags(tags) {
if (!tags) return false;
const EMPTY_TAGS_REGEX = RegExp('<[^>]*>\s*<\/[^>]*>');
return EMPTY_TAGS_REGEX.test(tags);
}
{item && !checkForEmptyTags(item.description) && (
<Link
style={{ display: 'block', paddingBottom: '2px' }}
title="View Details"
onClick={() => setIsOpen(!isOpen)}
{...aria}
>
View Details
<Icon icon={isOpen ? 'collapse_arrow' : 'expand_arrow'}
marginLeft="5px"
verticalAlign="bottom"
/>
</Link>
)}