@IlyaVakh

Как при нажатиии на строку в таблице №1 выводить дочерние данные в таблицу №2?

Добрый день. Имеется таблица DataGrid от Material UI. Код на TypeScript с React. Нужно, чтобы при нажатии по любой строке в первой таблице во вторую таблицу выводились соответствующие данные. Например подробная информация для конкретно этой строки. Изначально во 2 таблице нет данных. Т.е. это грубо говоря развертка. Хотим узнать подробности о какой-то строке -> кликаем на нее -> во 2 таблице отображается соответствующая вложенная информация. На данный момент вторая таблица не определена, так как не знаю, нужно создать экземлпяр той же или создавать совершенно другую и как-то перебрасывать в нее данные. Как я понимаю надо как-то связать нажатие кнопки в таблице 1 с появлением данных в таблице 2. Изначально хотел, чтобы просто как дерево раскрывалась строка с вложенностью, но столкнулся с проблемой, что такая функция есть только в Pro версии DataGrid. Сделал по туториалу ( https://www.youtube.com/watch?v=9Nzvw0ycYXw ). Но там данные выводятся в ту же самую строку без раскрытия. Пробовал подгрузить Pro версию, там в DataGrid есть параметр treeData (https://mui.com/x/react-data-grid/tree-data/), но слетел тип GridColumns, аналога которого почему-то нет в Pro версии. И слетело куча других импортов, которые попробовал заменить на прошные. Итог: в идеале нужно как описано выше вывод информации в соседнюю таблицу. Не в идеале просто такой же разворот в сворачиваемые строки как по ссылке с treeData. Казалось бы, тривиальная задача, но всю голову сломал. Спасибо, если кто откликнется
const Table = () => {
    const [editRowsModel, setEditRowsModel] = useState({});
    const [editRowData, setEditRowData] = useState({});
    const [pageSize, setPageSize] = useState(15);
    const [sortModel, setSortModel] = useState<GridSortItem[]>([{
        field: 'ddate', sort: 'desc',
    },]);
    const {data, loading} = useTypedSelector(state => state.data);
    const {role} = useTypedSelector(state => state.auth)
    const {fetchData} = useActions() 

    const getData = useCallback(() => {
        fetchData() 
    }, [data])

    useEffect(() => { 
        getData()
    }, []) 

    const addNewRecord = async () => {
        await axios.post('http://адрес/api/post', {
            ddate: new Date(),
            scontras: "",
            snumcontract: "",
            stype: "",
            mol: null,
            kurator: "",
            sdatenuminvoice: "",
            ddateaccept: "",
            sdatenumactosx: "",
            ddatetransfer: "",
            sfio: "",
            sdatenumvkn: "",
            sdatenumvkp: "",
            ddateaccept1: "",
            ddateaccept2: "",
            ddateload: "",
            nsum: ""
        })
            .catch((e) => {
                console.log(e)
            })
        getData()
    }
    const handleEdit = useCallback((model: any) => {

        const editedIds = Object.keys(model); 
        
        if (editedIds.length === 0 && Object.values(editRowsModel)[0] !== undefined) {
            updateRecord(Object.values(editRowData), Object.keys(editRowsModel)[0])
        } else {
            setEditRowData(model[editedIds[0]]); 
        }
        setEditRowsModel(model); 

    }, [editRowsModel, editRowData]);

    const updateRecord = async (data: any, id: any) => {
        if (role === 'eco') {
            await axios.patch('http://адрес/api/post/eco', {
                ddate: data[0].value,
                scontras: data[1].value,
                snumcontract: data[2].value,
                stype: data[3].value,
                mol: data[4].value,
                kurator: data[5].value,
                id: id
            })
                .catch((e) => console.log(e))
        } else if (role === 'mol') {
            await axios.patch('http://адрес/api/post/mol', {
                sdatenuminvoice: data[0].value,
                ddateaccept: data[1].value,
                sdatenumactosx: data[2].value,
                ddatetransfer: data[3].value,
                id: id
            })
                .catch((e) => console.log(e))
        } else if (role === 'ovko') {
            await axios.patch('http://адрес/api/post/ovko', {
                sfio: data[0].value,
                sdatenumvkn: data[1].value,
                sdatenumvkp: data[2].value,
                id: id
            })
                .catch((e) => console.log(e))
        } else if (role === 'kur') {
            
            await axios.patch('http://адрес/api/post/kur', {
                
                ddateaccept1: data[0].value, //1 столбец
                ddateaccept2: data[1].value, //2 столбец
                ddateload: data[2].value, //3 столбец
                nsum: data[3].value, //4 столбец
                id: id 
            })
                .catch((e) => console.log(e))
        }
    }
    
    const getFilteredRows = ({apiRef}: GridCsvGetRowsToExportParams) =>
        gridVisibleSortedRowIdsSelector(apiRef) 

        return (
            <GridToolbarContainer style={{order: 3}} {...props}>
                <GridToolbarColumnsButton/>
                <GridToolbarDensitySelector/>
                <GridToolbarFilterButton/>
                <Button
                    {...buttonBaseProps}
                    onClick={() => handleExport({getRowsToExport: getFilteredRows})}
                >
                    Экспорт
                </Button>
            </GridToolbarContainer>)
    }

        const detailStyles ={
            borderTop: "2px solid",
            borderTopColor: "primary.main",
            pt: 2
        }
        const [clickedIndex, setClickedIndex] = React.useState<number | undefined>(-1)

        const columns: GridColumns = [
       //добавил столбец с кнопками развертки сбоку. разворачивается информация в той же строке той же таблицы
         {
            field: 'id',
            headerName: 'Развернуть строку',
            width: 110,
            renderCell: (cellValues: GridRenderCellParams<number>) => {
                return (<IconButton 
                            onClick={ () => {clickedIndex === cellValues.value 
                                                    ? setClickedIndex(-1) 
                                                    : setClickedIndex(cellValues.value) }
                                            }
                                    >   {cellValues.value === clickedIndex 
                                            ? <KeyboardArrowUp/> 
                                            : <KeyboardArrowDown />} 
                        </ IconButton>)}, 
        },
        
        {
            field: 'ddate',
            headerName: 'Дата поступления',
            type: 'date',
            valueGetter: ({value}) => value && new Date(value),
            width: 150,
            editable: role === "eco",
            cellClassName: role === "eco" ? 'super-app-theme--cell' : '' }, 
        {
            field: 'scontras',
            headerName: 'Агент',
            width: 180,
            editable: role === "eco",
            cellClassName: role === "eco" ? 'super-app-theme--cell' : '',
            renderCell: (params: GridRenderCellParams) => (
                <Box><div>{params.value}</div><Collapse in={params.id === clickedIndex}><Box sx={detailStyles}>Expanded:  
                        {params.value}</Box></Collapse></Box> 
            }, 
        {
            field: 'snumcontract',
            headerName: '№  поставки',
            width: 200,
            editable: role === "eco",
            cellClassName: role === "eco" ? 'super-app-theme--cell' : '',
            renderCell: (params: GridRenderCellParams) => (
                <Box><div>{params.value}</div><Collapse in={params.id === clickedIndex}><Box sx={detailStyles}>Expanded:  {params.value}</Box></Collapse></Box> 
                )  },
        {
            field: 'stype',
            headerName: 'Тип',
            width: 250,
            editable: role === "eco",
            cellClassName: role === "eco" ? 'super-app-theme--cell' : '',
            renderCell: (params: GridRenderCellParams) => (
                <Box><div>{params.value}</div><Collapse in={params.id === clickedIndex}><Box sx={detailStyles}>Expanded:  {params.value}</Box></Collapse></Box> 
                ) },
    ];


//ТАБЛИЦЫ
    return (
            <div>
                <Paper className={classes.paper}>
                    <DataGrid
                        pagination
                        pageSize={pageSize}
                        className={classes.table}
                        onPageSizeChange={(newPageSize) => setPageSize(newPageSize)}
                        rowsPerPageOptions={[15, 30, 45]}
                        autoHeight
                        rows={data} //вывод строк
                        columns={columns} //столбцов
                        loading={loading}
                        components={{Toolbar: CustomToolbar, LoadingOverlay: LinearProgress}} //тулбар слева вверху таблицы
                        editRowsModel={editRowsModel}
                        editMode="row"
                        onEditRowsModelChange={handleEdit} //позволяет управлять состоянием редактирования. 
                        sortModel={sortModel}
                        onSortModelChange={(model) => setSortModel(model)}
                    />
                </Paper>
            </div>
  • Вопрос задан
  • 170 просмотров
Пригласить эксперта
Ответы на вопрос 1
semyonfedoseev
@semyonfedoseev
Могу загуглить вместо тебя
Извините, но у Вас слишком много букв в коде. В таких случаях, лучше всего, отрефакторить лишнее, декомпозировать оставшееся и оформлять код в онлайн IDE (например, CodeSandbox). К тому же, подобное оформление вопроса неудобно читать.

Мой вариант реализации для таблицы DataGrid:
https://codesandbox.io/s/material-demo-forked-gu2f...

Для вывода дополнительных дочерних строк в каждой ячейке рендерится объект с дочерними строками через map. Можете оформить так, как Вам удобнее, я лишь показал минимальный пример вывода данных.

Возможно, Вам подойдёт другой вид таблицы из урока этого же автора, если желаете сделать таблицу более похожей на таблицу из платной версии:
https://smartdevpreneur.com/how-to-use-the-mui-col...

Вы сможете также выводить дополнительные строки через map, но уже полностью всю строку.

Вероятно, Вас могла бы заинтересовать таблица Ant Design:
https://ant.design/components/table#components-tab...
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы