How to apply style of TableRow similar to TableHead in material-ui / mui?

457 Views Asked by At

Currently I'm trying to apply the styling of TableHead to TableRow as well but I'm getting Warning: validateDOMNesting(...): cannot appear as a child of . how to fix this without warning message.

CollapisbleTableRow.js

import React, { Fragment, useCallback } from 'react'
import { makeStyles, IconButton, Checkbox, Collapse, TableCell, TableHead, TableRow } from '@mui/material'
import DeleteIcon from '@mui/icons-material/Delete'
import FileCopyIcon from '@mui/icons-material/FileCopy'
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'
import isEmpty from 'lodash/fp/isEmpty'
import ValidatedFramework from '../validated-framework'
import { formatError } from '../../tiles/client-search/utils'


const useRowStyles = makeStyles({
    root: {
        '& > *': {
            borderBottom: 'unset',
        },
    },
})

export default function CollapsibleTableRow({
    row,
    rowIndex,
    rowHeader,
    rowForm,
    onChangeRow,
    handleChange,
    onAddRow,
    onRemoveRow,
    onCollapseRow,
}) {
    const classes = useRowStyles()
    const handleColumnChange = useCallback(event => {
        const name = event.currentTarget.name || event.target.name
        const value = event.currentTarget.value || event.target.value
        if (name === 'urgent') {
            handleChange(value)
        } else if (name === 'addRow') {
            onAddRow(value)
        } else if (name === 'removeRow') {
            onRemoveRow(value)
        } else {
            onCollapseRow(value)
        }
    })

    return (
        <Fragment key={rowIndex}>
            <TableRow className={classes.root} key={rowIndex}>
                <TableCell style={{ width: '30px' }}>
                    <IconButton
                        size='small'
                        name={'arrow'}
                        value={rowIndex}
                        onClick={handleColumnChange}
                    >
                        {row.isCollapsed ? (
                            <KeyboardArrowDownIcon style={{ fontSize: '1.5rem', transform: 'scale(1.5)' }} />
                        ) : (
                            <KeyboardArrowRightIcon style={{ fontSize: '1.5rem', transform: 'scale(1.5)' }} />
                        )}
                    </IconButton>
                </TableCell>
                <TableCell style={{
                    color: 'green',
                    width: '30px'
                }}>
                    <div
                        style={{
                            alignItems: 'center',
                            display: 'flex',
                            height: '2em'
                        }}
                    >
                        {!isEmpty(row.validationErrors) && <ValidatedFramework value={formatError(row.validationErrors)}/>}
                        {isEmpty(row.validationErrors) && row.status === 'SUCCESS' && <ValidatedFramework value={[ ]}/>}
                    </div>
                </TableCell>
                {rowHeader(row, rowIndex, onChangeRow)}
                <TableCell
                    style={{
                        marginBottom: `${row.isCollapsed ? 'none' : '1px solid lightgray'}`,
                        width: '30px'
                    }}
                >
                    <div
                        style={{
                            alignItems: 'center',
                            display: 'flex',
                            height: '2em'
                        }}
                    >
                        <IconButton size='small' onClick={handleColumnChange}>
                            <Checkbox
                                checked={row.urgentRequest}
                                name={'urgent'}
                                value={rowIndex}
                                color='primary'
                                size='medium'
                                disabled={row.status === 'SUCCESS'}
                                inputProps={{
                                    'aria-label': 'secondary checkbox',
                                }}
                            />
                        </IconButton>
                    </div>
                </TableCell>
                <TableCell
                    style={{
                        marginBottom: `${row.isCollapsed ? 'none' : '1px solid lightgray'}`,
                        width: '30px'
                    }}
                >
                    <div
                        style={{
                            alignItems: 'center',
                            display: 'flex',
                            height: '2em'
                        }}
                    >
                        <IconButton
                            size='small'
                            name={'addRow'}
                            value={rowIndex}
                            onClick={handleColumnChange}
                        >
                            <FileCopyIcon style={{ fontSize: '1.1rem', transform: 'scale(1.1)' }}/>
                        </IconButton>
                        <IconButton
                            size='small'
                            name={'removeRow'}
                            value={rowIndex}
                            onClick={handleColumnChange}
                        >
                            <DeleteIcon style={{ fontSize: '1.2rem', transform: 'scale(1.2)' }}/>
                        </IconButton>
                    </div>
                </TableCell>
            </TableRow>
            <TableRow> // this is the main place I want to change styling 
                <TableCell
                    style={{ padding: 0 }}
                    colSpan={12}
                >
                    <Collapse
                        in={row.isCollapsed}
                        timeout='auto'
                        unmountOnExit
                    >
                        <TableHead style={{display: 'flex'}}>
                            <TableCell style={{flex: '1'}}>{rowForm(row, rowIndex, onChangeRow)}</TableCell>
                        </TableHead>
                    </Collapse>
                </TableCell>
            </TableRow>
        </Fragment>
    )
}
2

There are 2 best solutions below

0
KARTHIKEYAN.A On BEST ANSWER

Finally I realized that Instead of using TableHead inside TableRow I have stlied the TableRow and TableCell in the following way and used it in component.

import React, { Fragment, useCallback } from 'react'
import { makeStyles, Checkbox, Collapse, IconButton } from '@mui/material'
import TableCell, { tableCellClasses } from '@mui/material/TableCell'
import { styled } from '@mui/material/styles'
import TableRow from '@mui/material/TableRow'
import DeleteIcon from '@mui/icons-material/Delete'
import FileCopyIcon from '@mui/icons-material/FileCopy'
import KeyboardArrowRightIcon from '@mui/icons-material/KeyboardArrowRight'
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown'
import isEmpty from 'lodash/fp/isEmpty'
import ValidatedFramework from '../validated-framework'
import { formatError } from '../../tiles/client-search/utils'


const useRowStyles = makeStyles({
    root: {
        '& > *': {
            borderBottom: 'unset',
        },
    },
})

const StyledTableCell = styled(TableCell)(({ theme }) => ({
    [`&.${tableCellClasses.head}`]: {
        backgroundColor: theme.palette.common.black,
        color: theme.palette.common.white,
    },
    [`&.${tableCellClasses.body}`]: {
        fontSize: 14,
    },
}))

const StyledTableRow = styled(TableRow)(({ theme }) => ({
    '&:nth-of-type(even)': {
        backgroundColor: theme.palette.action.hover,
    },
}))

export default function CollapsibleTableRow({
    row,
    rowIndex,
    rowHeader,
    rowForm,
    onChangeRow,
    handleChange,
    onAddRow,
    onRemoveRow,
    onCollapseRow,
}) {
    const classes = useRowStyles()
    const handleColumnChange = useCallback(event => {
        const name = event.currentTarget.name || event.target.name
        const value = event.currentTarget.value || event.target.value
        if (name === 'urgent') {
            handleChange(value)
        } else if (name === 'addRow') {
            onAddRow(value)
        } else if (name === 'removeRow') {
            onRemoveRow(value)
        } else {
            onCollapseRow(value)
        }
    })

    return (
        <Fragment key={rowIndex}>
            <StyledTableRow className={classes.root} key={rowIndex}>
                <StyledTableCell style={{ width: '30px' }}>
                    <IconButton
                        size='small'
                        name={'arrow'}
                        value={rowIndex}
                        onClick={handleColumnChange}
                    >
                        {row.isCollapsed ? (
                            <KeyboardArrowDownIcon style={{ fontSize: '1.5rem', transform: 'scale(1.5)' }} />
                        ) : (
                            <KeyboardArrowRightIcon style={{ fontSize: '1.5rem', transform: 'scale(1.5)' }} />
                        )}
                    </IconButton>
                </StyledTableCell>
                <StyledTableCell style={{
                    color: 'green',
                    width: '30px'
                }}>
                    <div
                        style={{
                            alignItems: 'center',
                            display: 'flex',
                            height: '2em'
                        }}
                    >
                        {!isEmpty(row.validationErrors) && <ValidatedFramework value={formatError(row.validationErrors)}/>}
                        {isEmpty(row.validationErrors) && row.status === 'SUCCESS' && <ValidatedFramework value={[ ]}/>}
                    </div>
                </StyledTableCell>
                {rowHeader(row, rowIndex, onChangeRow)}
                <StyledTableCell
                    style={{
                        marginBottom: `${row.isCollapsed ? 'none' : '1px solid lightgray'}`,
                        width: '30px'
                    }}
                >
                    <div
                        style={{
                            alignItems: 'center',
                            display: 'flex',
                            height: '2em'
                        }}
                    >
                        <IconButton size='small' onClick={handleColumnChange}>
                            <Checkbox
                                checked={row.urgentRequest}
                                name={'urgent'}
                                value={rowIndex}
                                color='primary'
                                size='medium'
                                disabled={row.status === 'SUCCESS'}
                                inputProps={{
                                    'aria-label': 'secondary checkbox',
                                }}
                            />
                        </IconButton>
                    </div>
                </StyledTableCell>
                <StyledTableCell
                    style={{
                        marginBottom: `${row.isCollapsed ? 'none' : '1px solid lightgray'}`,
                        width: '30px'
                    }}
                >
                    <div
                        style={{
                            alignItems: 'center',
                            display: 'flex',
                            height: '2em'
                        }}
                    >
                        <IconButton
                            size='small'
                            name={'addRow'}
                            value={rowIndex}
                            onClick={handleColumnChange}
                        >
                            <FileCopyIcon style={{ fontSize: '1.1rem', transform: 'scale(1.1)' }}/>
                        </IconButton>
                        <IconButton
                            size='small'
                            name={'removeRow'}
                            value={rowIndex}
                            onClick={handleColumnChange}
                        >
                            <DeleteIcon style={{ fontSize: '1.2rem', transform: 'scale(1.2)' }}/>
                        </IconButton>
                    </div>
                </StyledTableCell>
            </StyledTableRow>
            <StyledTableRow>
                <StyledTableCell
                    style={{ padding: 0 }}
                    colSpan={12}
                >
                    <Collapse
                        in={row.isCollapsed}
                        timeout='auto'
                        unmountOnExit
                    >
                        <div style={{display: 'flex'}}>
                            <span style={{flex: '1'}}>{rowForm(row, rowIndex, onChangeRow)}</span>
                        </div>
                    </Collapse>
                </StyledTableCell>
            </StyledTableRow>
        </Fragment>
    )
}
0
Irfan Alvi On

There are multiple mistakes in your approach, I'm trying to mention few of those as simple as possible.

  1. You have to follow the structure of Mui Table Component. You should not put TableHead inside Collapse without Table & TableBody component, you also didnt created a TableRow inside TableHead. You will get those error if you are not following Table structure.

  2. You should not use div inside TableRow or TableCells, use Box instead. Divs wont gonna brick your code, its just to prevent weird errors in console.

  3. MakeStyles is deprecated now, theirs more styling methods in MUI v5 which you can use.

  4. For MUI component styling, its better to style with system/sx prop.

         <TableRow> // Last row from your code
            <TableCell
                sx={{ padding: 0 }}
                colSpan={12}
            >
                <Collapse
                    in={row.isCollapsed}
                    timeout='auto'
                    unmountOnExit
                >
                  <Table>
                    <TableHead sx={{display: 'flex'}}>
                        <TableCell sx={{flex: '1'}}>{rowForm(row, rowIndex, onChangeRow)}</TableCell>
                    </TableHead>
                   </Table>
                </Collapse>
            </TableCell>
        </TableRow>
    

Hopefully this gonna clear your questions :D