How to fix flickering issue in table row with Ant Design Table? - css

I am using Ant Design on my React.js application. I used Table component. I have two columns: one for an input number field, and another for input field and will be editable on hover. When I hover on each row, there is a flicker issue which does not happen if I have input number field only or an input field only. When I have them both, it is like having an extra margin top or padding. When I check the dev tools, there were no added styling. I even adjust its min-height but no effect.
Flickering issue when hovering on table row
const columns = [
{
render: (_, { id, value }, index) => {
if (editingRow === id) {
return (
<Form.Item
name="value"
style={{ margin: 0 }}
>
<div onBlur={() => setEditingRow(null)}>
<InputNumber
value={value}
onChange={numValue => {
onChange(
{ id, value: numValue },
);
}}
/>
</div>
</Form.Item>
);
} else {
return (
<Form.Item style={{ margin: 0 }}>
<Input value={value} disabled />
</Form.Item>
);
}
}
},
{
render: (_, { id, title }, index) => {
if (editingRow === id) {
return (
<Form.Item
name="value"
style={{ margin: 0 }}
>
<div onBlur={() => setEditingRow(null)}>
<Input
value={value}
onChange={event => {
event.persist();
onChange(
{ id, title: event.target.value },
);
}}
/>
</div>
</Form.Item>
);
} else {
return (
<Form.Item style={{ margin: 0 }}>
<Input value={value} disabled />
</Form.Item>
);
}
}
},
]

Related

React-beautiful-dnd: lazy loaded component keeps falling back to suspense when dragged

I have a react component that dynamically loads a widget component using react lazy, with the component path passed as a prop.
It renders fine, but when I drag it, the component flickers between its Suspense fallback and the fully rendered component. How can I prevent the Suspense fallback from being shown while dragging?
The draggable list looks like this:
<DragDropContext
onDragEnd={result => {
console.log(result);
reorder({ result, previousData: dashboard.data });
}}
>
<Title title={`Dashboard`} />
<Droppable droppableId={"dashboard"}>
{(
provided
// snapshot
) => {
return (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={{
display: "flex",
flexDirection: "column"
}}
>
{Array.isArray(dashboardItems.data) && dashboardItems.data.length > 0 ? (
dashboardItems.data.map((item: any, index: number) => {
return (
<Draggable key={item.id} draggableId={item.id} index={index}>
{(provided, snapshot) => {
return (
<div ref={provided.innerRef} {...provided.draggableProps}>
<WidgetCard item={item} dragHandleProps={provided.dragHandleProps} />
{!snapshot.isDragging && <AddWidgetControl />}
</div>
);
}}
</Draggable>
);
})
) : (
<Button
onClick={() =>
addDashboardItem.mutate({
index: 0,
dashboardItem: widgets.overview
})
}
>
<Typography variant="body2">Add</Typography>
</Button>
)}
{provided.placeholder}
</div>
);
}}
</Droppable>
</DragDropContext>
and the WidgetCard component that conditionally renders the widgets using lazy looks like this:
const WidgetCard = ({
item,
dragHandleProps
}: {
item: DashboardItemEntity,
dragHandleProps?: any
}) => {
{...}
const renderLoader = () => <p>Loading</p>;
const WidgetComponent = lazy(() => import(`../${item.component}`));
{...}
return (
{...}
<CardContent sx={{ marginTop: 0, paddingTop: 0 }}>
{/* {description} */}
<Box sx={{ marginLeft: 2 }}>
<Suspense fallback={renderLoader()}>
<WidgetComponent item={item} />
</Suspense>
</Box>
</CardContent>
{...}
);
};

Nested flex item divs rendered using React not restricting themselves to coequal/correct size?

I am attempting to render a custom Table component in React that will render [ "linear"-looking ] sub-tables, if and only if the values of its object rows prop are themselves of type 'object'. To do this I have my parent Table component, that renders a child TableRow component, that then does the conditional rendering of either a SubTable component or a TableInnerSquare component.
So far it works perfectly for the base condition [ when the properties of the rows object are simple ], but when I try to render sub-tables, the TableRows overflow the width of their container and I can't figure out how to stop this from happening.
Table component:
function Table(props) {
const { rows, columns, tableWidth, rowHeight } = props;
// rows here should be an array of rows containing objects w/ properties keyed by column names
// columns should just be an array of column names
return (
<div className='g-table'
style={{
display: 'flex',
width: tableWidth,
flexDirection: 'column',
margin: '5% auto',
}}
>
<div className='column-id-container'
style={{
display: 'flex',
width: tableWidth,
height: rowHeight,
}}
>
{ columns.map((column,idx) => {
return (
<div className='column-id'
style={{
backgroundColor: 'lightblue',
border: '1px solid blue',
width: '100%',
overflow: 'hidden',
padding: '2%',
}}
key={idx}
>
{ column }
</div>
);
}) }
</div>
<div className='rows-container'>
{ rows.map((row,idx) => {
return (
<TableRow
key={idx}
row={row}
rowId={idx}
tableWidth={tableWidth}
rowHeight={rowHeight}
columns={columns}
/>
);
}) }
</div>
</div>
);
};
TableRow component:
function TableRow(props) {
const { columns, row, rowId, tableWidth, rowHeight } = props;
// row should be an object with keys for each column here;
// columns should be an array
console.log('columns:');
console.log(columns);
console.log('row:');
console.log(row);
return (
<div className='table-row'
style={{
display: 'flex',
width: tableWidth,
}}
>
{ columns.map((property,idx) => {
if (typeof (row[property]) === 'object') {
return (
<SubTable
dataObject={row[property]}
rowHeight={rowHeight} // so for the SubTablesTable the row should be an object of objects
key={idx}
/>
);
} else {
return (
<TableInnerSquare
innerData={row[property]}
rowHeight={rowHeight}
key={idx}
/>
);
}
}) }
</div>
);
}
SubTable:
function SubTable(props) {
const { dataObject, rowHeight } = props;
console.log('dataObject:');
console.log(dataObject);
return (
<div className='sub-table'
style={{
width: 'auto',
display: 'flex',
flex: '1',
}}
>
{ Object.entries(dataObject).map((entry,idx) => {
return (
<div className='sub-table-inner'
style={{
display: 'flex',
overflow: 'hidden',
}}
>
<TableInnerSquare
rowHeight={rowHeight}
innerData={entry[0]}
/>
<TableInnerSquare
rowHeight={rowHeight}
innerData={entry[1]}
/>
</div>
);
}) }
</div>
);
}
TableInnerSquare:
function TableInnerSquare(props) {
const { innerData, rowHeight } = props;
return (
<div
className='table-inner-square'
style={{
backgroundColor: 'gold',
border: '1px solid red',
height: rowHeight,
overflow: 'hidden',
padding: '2%',
width: '100%',
}}
>
{ innerData }
</div>
);
}
Any help figuring out how to restrict TableRows containing SubTables to having width tableWidth [ which like I said the TableRows containing TableInnerSquares already seem to do? ] would be appreciated!
You can set overflow: hidden on a div, but its parent divs will still recognize the content as present and grow to contain it. You need to set overflow: hidden on the div with class sub-table [ in component SubTable ] here, in order for the sub-tables to hide the overflows of their inner divs.

How to style TextField used as Select of muiv5?

How to reduce the padding of TextField used as Select of muiv5. And Also the max-height of dropdown option plus the padding of individual list item of that dropdown.
I can't wrap my head around sx prop. Can someone please help me understand how to override styles uisng sx props. Thanks in advance.
const pageList = useMemo(() => {
return range(1, 100).map((item, i) => {
return (
<MenuItem
key={i}
value={item}
sx={{
'& .MuiMenuItem-root.Mui-selected': {
padding: '0px 40%',
},
}}
>
{item}
</MenuItem>
);
});
}, [lastPage]);
<TextField
InputLabelProps={{ shrink: false }}
margin="dense"
variant="outlined"
size="small"
select
value={currentPage}
onChange={(e) => {
const page = e.target.value ? Number(e.target.value) : 0;
onPageChange(page);
}}
sx={{
'&.MuiInputBase-input': {
padding: '10px',
},
'&.MuiList-root': {
maxHeight: '100px',
},
}}
>
{pageList}
</TextField>

How do I target a span within a label element when a checkbox is checked using React Material UI createStyles?

I'm trying to target the span, but haven't been able to do so. I want to be able to change the background color of the span when the checkbox is checked.
<div className={classes.container}>
<input type="checkbox" id="checkboxid" />
<label className={classes.label} htmlFor="checkboxid">
<span className={classes.labelText}>Target</span>
</label>
</div>
container: {
'& input:checked': {
'& label': {
'& $labelText': {
background: 'red'
}
}
}
}
While label is not inside the input but a sibiling you need to make use of the css sibling selector +
In your context
const useSpanStyles = makeStyles({
container: {
'& input:checked + label': {
'& span': {
background: 'red'
}
},
},
label: {},
labelText: {}
});
export function ComponentXYZ(){
const classes = useSpanStyles();
return (
<div className={classes.container}>
<input type="checkbox" id="checkboxid" />
<label className={classes.label} htmlFor="checkboxid">
<span className={classes.labelText}>Target</span>
</label>
</div>
);
}
To be honest with you, if you are using MUI you should've used their components as its easier to compose and build UI with
Here's my suggestion
function ComponentXYZ(){
const [checked, setIsChecked] = useState(false);
const checkedHandler = useCallback(function _checkedHandler(event: any) {
setIsChecked(event.target.checked);
}, []);
return (
<div>
<FormGroup>
<FormControlLabel
control={<Checkbox
checked={checked}
onChange={checkedHandler}
/>}
label={
<Typography style={{ background: checked ? 'red' : 'inherit' }}>
{'Label That change color'}
</Typography>
}
/>
</FormGroup>
</div>
);
}

How to change from one text field to another

I have a 4 text fields which are meant to be used to type in a 4 digit code sent to the phone. How can I automatically change to the next field if a number is written and for it not to take anything apart from numbers
Ill attach a picture along with my code base
// flow
import React, { useRef } from 'react';
import { signup } from '../../assets/images';
import FormDiv from '../shared/Sign-in-div';
import ImageDiv from '../shared/Image-div';
import { Nunito32, Nunito20 } from '../shared/nunito/nunito';
import ImageContainer from '../shared/image-container';
import OtpField from '../shared/otp-field';
import PinkButton from '../shared/button-color-pink';
let [fieldOne, fieldTwo, fieldThree, fieldFour] = useRef(null);
const onChange = field => {
field.focus();
};
const SignUpVerification = () => (
<div style={{ display: 'flex' }}>
<FormDiv style={{ textAlign: 'center' }}>
<Nunito32
style={{
display: 'inline-block',
textAlign: 'center',
marginRight: 236,
marginLeft: 200,
}}
>
Verify your mobile number by entering the code we sent you
</Nunito32>
<div style={{ flexDirection: 'row' }}>
<OtpField
ref={input => {
fieldOne = input;
}}
style={{ marginRight: 10.5 }}
onChange={() => onChange(fieldTwo)}
/>
<OtpField
ref={input => {
fieldTwo = input;
}}
onChange={() => onChange(fieldThree)}
style={{ marginRight: 10.5 }}
/>
<OtpField
ref={input => {
fieldThree = input;
}}
onChange={() => onChange(fieldFour)}
style={{ marginRight: 10.5 }}
/>
<OtpField
ref={input => {
fieldFour = input;
}}
style={{ marginRight: 10.5 }}
/>
</div>
<PinkButton style={{ marginTop: 75 }}>Continue</PinkButton>
<Nunito20>Send again</Nunito20>
</FormDiv>
<ImageContainer>
<ImageDiv bg={signup} src={signup} alt="logo" />
</ImageContainer>
</div>
);
export default SignUpVerification;
It now gives me 2 errors that fieldOne is created but not used and ×
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
How about re-render when the state you change?
Handling focus is good task for Refs in React. So idea will be to have refs for input fields and in onChange event handler check if user typed 3 digits and turn focus to next input.
I have created demo on codesandbox to showcase how it works
Since you are making use of React JS, you can go forward with React Refs and the DOM where you can select the nodes and handle the focus pragmatically. This is a sample implementation. Find the implementation here.
class App extends React.Component{
componentDidMount(){
this.fieldOne.focus();
}
onChange(field) {
field.focus();
}
render() {
return(
<div>
<input
onChange={() => this.onChange(this.fieldTwo)}
ref={(input) => { this.fieldOne = input; }}
placeholder="First Field"
/>
<input
onChange={() => this.onChange(this.fieldThree)}
ref={(input) => { this.fieldTwo = input; }}
placeholder="Second Field"
/>
<input
onChange={() => this.onChange(this.fieldFour)}
ref={(input) => { this.fieldThree = input; }}
placeholder="Third Field"
/>
<input
ref={(input) => { this.fieldFour = input; }}
placeholder="Fourth Field"
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/15.6.1/react-dom.min.js"></script>
<div class="container-fluid" id="main">
<div class="row">
<div class="col-xs-12">
<div id="root"></div>
</div>
</div>
</div>

Resources