I'm using MUIDataTable but I can't center the headers. I need to center the headers vertically and horizontally. Please someone can help me:
I'm trying with this code but don't work:
columns: [{
name: <strong>#</strong>,
options: {
filter: false,
download: false,
print: false,
}
},
{ name: <strong>Empresa</strong>, options: { align: "center"} },
{ name: <strong>Ruc</strong>, options: { align: "center"} },
{ name: <strong>Fecha</strong>, options: { align: "center"} },
{ name: <strong>Usuario Aginado</strong>, options: { align: "center"} },
{ name: <strong>Usuario Ediccion</strong>, options: { align: "center"} },
{ name: <strong>Indicador</strong>, options: { align: "center"} },
{ name: <strong>Objetivo</strong>, options: { align: "center"} },
{ name: <strong>Estado</strong>, options: { align: "center"} },
{ name: <strong>Tiempo Excedido</strong>, options: { align: "center"} },
{
name: <strong><i className="zmdi zmdi-edit"></i></strong>,
options: {
filter: false,
download: false,
print: false
}
}
],
...
<MUIDataTable
data={this.state.data}
columns={this.state.columns}
options={this.state.options}
/>
Please check this example:
import React from "react";
import ReactDOM from "react-dom";
import MUIDataTable from "mui-datatables";
export default class MuiDatatable extends React.Component {
render() {
const columns = [
{
label: "Name",
name: "Name",
options: {
filter: true,
customHeadRender: (columnMeta, updateDirection) => (
<th key={1} onClick={() => updateDirection(2)} style={{cursor: 'pointer'}}>
{columnMeta.name}
</th>
)
}
},
{
label: "Title",
name: "Title",
options: {
filter: true,
sortDirection: 'asc',
customHeadRender: (columnMeta, updateDirection) => (
<th key={2} onClick={() => updateDirection(2)} style={{cursor: 'pointer'}}>
{columnMeta.name}
</th>
)
}
},
{
name: "Location",
options: {
filter: false,
customHeadRender: (columnMeta, updateDirection) => (
<th key={3} onClick={() => updateDirection(2)} style={{cursor: 'pointer'}}>
{columnMeta.name}
</th>
)
}
},
{
name: "Age",
options: {
filter: true,
sort: false,
customHeadRender: (columnMeta, updateDirection) => (
<th key={4} onClick={() => updateDirection(2)} style={{cursor: 'pointer'}}>
{columnMeta.name}
</th>
)
}
},
{
name: "Salary",
options: {
filter: true,
sort: false,
customHeadRender: (columnMeta, updateDirection) => (
<th key={5} onClick={() => updateDirection(2)} style={{cursor: 'pointer'}}>
{columnMeta.name}
</th>
)
}
}
];
const data = [
["Gabby George", "Business Analyst", "Minneapolis", 30, "$100,000"],
["Aiden Lloyd", "Business Consultant", "Dallas", 55, "$200,000"]
];
const options = {
selectableRows: "none"
};
return (
<MUIDataTable
title={"ACME Employee list"}
data={data}
columns={columns}
options={options}
/>
);
}
}
I only added the following code to my jss to make the header center:
MUIDataTableHeadCell: {
toolButton: {
justifyContent: 'center'
},
},
First off;
Import 'createTheme' and 'ThemeProvider';
import { createTheme, ThemeProvider } from '#mui/material/styles'
Next;
const getMuiTheme = () =>
createTheme({
components: {
MuiButton: {
styleOverrides: {
root: {
fontFamily: 'poppins',
justifyContent: 'center',
fontWeight: 'bold',
},
},
},
},
})
That's all...
The MuiButton component controls the text header section. Feel free to modify to your taste. If you wish to align to left like most people would like to, you can just set paddingLeft to '1px'. In your case, justifyContent: center should do
Related
I've created a form using antd-form-builder which contains 3 parts. In "Routines" part user can add several "Tasks" I need to collect each task information by clicking on the "Add Routine" button in an array like this:
"routinesList": [
{
"routinType": 1,
"intervalDays": 20,
"nextDueDate": "2023-01-08T15:46:33.185Z",
"kindOfDate": 1,
"serviceProvider": "string",
"sop": "string",
"displayBeforeDue": 1,
"lastDate": "2023-01-08T15:46:33.185Z",
"nextDate": "2023-01-08T15:46:33.185Z",
"taskId": 1
}
]
and finally send all 3 parts data to the server by clicking on submit button.
how can I do it?
here is my code for Routine part of the form:
import React, { Fragment, useEffect, useState, useCallback } from "react"
import { Form, List, Select, Input, InputNumber, Row, Col, Button } from "antd"
import FormBuilder from "antd-form-builder"
import { MinusCircleOutlined, PlusOutlined } from "#ant-design/icons"
import axios from "axios"
const Option = Select.Option
const IntervalInput = ({ value, onChange }) => (
<Row gutter={10}>
<Col span={16}>
<InputNumber min={1} style={{ width: "100%" }} value={value.number} onChange={(v) => onChange({ number: v, unit: value.unit })} />
</Col>
<Col span={8}>
<Select value={value.unit} onChange={(v) => onChange({ number: value.number, unit: v })}>
<Option value="1">Day(s)</Option>
<Option value="2">Month(s)</Option>
</Select>
</Col>
</Row>
)
function RoutineInfo(props) {
const [form] = Form.useForm()
const [routineData, setRoutineData] = useState([])
const [opts, setOpts] = useState({ sop: [], service: [] })
useEffect(() => {
const fetchOpts = async () => {
const serviceData = await axios("api?id=3")
setOpts({ sop: [], service: serviceData.data })
}
fetchOpts()
}, [])
const optsService = opts.service
const serviceOptions = optsService.map(({ typeValue }) => typeValue)
const columns = 2
const meta = {
columns,
fields: [
{
key: "routineType",
label: "Routine Type",
widget: "select",
options: [
{ label: "Calibration", value: 1 },
{ label: "Maintenance", value: 2 },
],
initialValue: 1,
colSpan: 2,
},
{
key: "interval",
label: "Interval",
forwardRef: true,
widget: IntervalInput,
initialValue: { number: 30, unit: "Days" },
},
{
key: "lastDate",
label: "Last Due Date",
widget: "date-picker",
widgetProps: { style: { width: "100%" } },
colSpan: 2,
},
{
key: "nextDate",
label: "Next Due Date",
widget: "date-picker",
widgetProps: { style: { width: "100%" } },
colSpan: 2,
},
{
key: "displayBeforeDue",
label: "Display Before Due",
widget: "number",
colSpan: 2,
},
{
key: "sop",
label: "SOP",
widget: "select",
colSpan: 2,
},
{
key: "serviceProvider",
label: "Service Provider",
widget: "select",
//onChange: (e) => setRoutineData(e.target.value),
options: serviceOptions,
widgetProps: { showSearch: true },
colSpan: 2,
},
{
key: "task",
label: "Task",
//forwardRef: true,
widget: "select",
widgetProps: { showSearch: true },
options: [
{ label: "Pre-filter Replacement", value: 1 },
{ label: "Oil Change", value: 2 },
],
colSpan: 2,
},
],
}
const getData = () => {
console.log(routineData)
}
return (
<Fragment>
<fieldset className="form-frame">
<FormBuilder meta={meta} form={form} />
<Form.Item className="ant-form-item--btn">
<Button type="primary" onClick={getData}>
Add Routine
</Button>
</Form.Item>
</fieldset>
<div
id="scrollableDiv"
style={{
//height: 272,
overflow: "auto",
padding: "0 16px",
border: "1px solid rgba(140, 140, 140, 0.35)",
}}
>
// here I want to display tasks in a list
<List
itemLayout="horizontal"
//dataSource={data}
renderItem={(item) => (
<List.Item
actions={[
<a key="list-edit">edit</a>,
<a onClick={() => axios.delete(`api/${item.id}`, item)} key="list-delete">
delete
</a>,
]}
>
<List.Item.Meta title={item.typeValue} />
</List.Item>
)}
/>
</div>
<Form.Item className="ant-form-item--btn">
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Fragment>
)
}
export default RoutineInfo
enter image description here
as shown in the above image i want to display it in a muidatatable with grouped header
i tried this below code but i didn't get proper table with grouped header it shows only the headers not to the grouped headers
const columns=[
{
name: 'Name',
headerCellProps: {
style: {
textAlign: 'center',
border: 0,
background: blue[500],
},
},
columns: [
{
name: 'firstName',
header: 'First Name',
},
{
name: 'lastName',
header: 'Last Name',
},
],
},
{
name: 'age',
header: 'Age',
headerCellProps: {
style: {
background: orange[500],
},
},
},
{
name: 'Job',
headerCellProps: {
style: { textAlign: 'center', border: 0, background: purple[500] },
},
columns: [
{
name: 'jobTitle',
header: 'Title',
},
{
name: 'jobArea',
header: 'Area',
},
],
},
]
const columns = [
{
name: 'Health & Safety',
// label:'Manual Handling',
options: {
filter: true,
customHeadRender: (tableMeta,value) =>
(<>
<th className={classes.thhead} >
<th className={classes.thsubhead} >
<span className={classes.headSpan} >Health & Safety</span>
{EMP.filter( item => item.TrainingCategory === 'Health & Safety').map((EMPLOYE)=>{
return(
<th style={{border:"0px",paddingLeft:"0px",paddingTop:"0px",paddingBottom:"0px"}} >
{/* <span className={classes.headSpan} >Health & Safety</span> */}
<th className={classes.headvalueOne} >
{EMPLOYE.TrainingName}
</th>
</th>
)
})
}
</th>
</th>
</>),
customBodyRender: (value) => (
<td className={classes.tdHead}>
<td className={classes.tdsubHead} >
{ EMP?
EMP.map((EMPLOYE)=>{
return(
<td className={classes.TablevalueOne} >{EMPLOYE.JobTitileNumber}</td>
)
}):null}
</td>
</td>
),
}
},
},
];
I'm working on a family tree where children can be moved to other parents. Issue comes when I reorder a family on drag and drop(DnD), it doesn't update in the formik values object. Also when I delete a child on the DnD it doesn't update the DnD objects but updates the formik values objects.
Codesandbox link is: https://codesandbox.io/s/kind-hermann-lqve6
Below is the code:
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Formik, FieldArray } from "formik";
import { Button, Form } from "antd";
import { DndProvider } from "react-dnd";
import HTML5Backend from "react-dnd-html5-backend";
import Sortly, { ContextProvider, useDrag, useDrop } from "react-sortly";
const FormItem = Form.Item;
const ItemRenderer = props => {
const {
index,
data: { text, kids }
} = props;
const [, drag] = useDrag();
const [, drop] = useDrop();
return (
<FieldArray
name="family.parents"
render={arrayHelpers => (
<div ref={drop} style={{ width: "40vw" }} key={index}>
<div
ref={drag}
style={{
padding: "0.5rem 1rem",
marginBottom: ".5rem",
backgroundColor: "green",
cursor: "move",
color: "white",
width: "320px"
}}
>
{`${text}`}
<FormItem style={{ display: "inline-block" }}>
<span className="parent-utility">
<Button
className="ant-btn"
shape="circle"
size="small"
style={{ color: "#ffa500" }}
onClick={() => arrayHelpers.remove(index)}
>
Delete
</Button>
</span>
</FormItem>
</div>
<KSortableTree kidsTree={kids} position={index} />
</div>
)}
/>
);
};
const ItemRendererA = props => {
const {
index,
position,
data: { text }
} = props;
const [, drag] = useDrag();
const [, drop] = useDrop();
return (
<FieldArray
name={`family.parents[${position}].kids`}
render={arrayHelpers => (
<>
<div ref={drop} style={{ width: "40vw" }}>
<div
ref={drag}
style={{
border: "1px dashed #70B5DC",
padding: "0.5rem 1rem",
marginBottom: ".5rem",
marginLeft: "3rem",
backgroundColor: "white",
cursor: "move",
color: "#70B5DC",
width: "17rem"
}}
>
{`${text}`}
<FormItem style={{ display: "inline-block" }}>
<span className="answer-utility">
<Button
className="ant-btn"
shape="circle"
size="small"
style={{ color: "#ffa500" }}
onClick={() => {
arrayHelpers.remove(index);
}}
>
Delete
</Button>
</span>
</FormItem>
</div>
</div>
</>
)}
/>
);
};
const PSortableTree = parentTree => {
const [items, setItems] = useState(parentTree.parentTree);
const handleChange = newItems => {
setItems(newItems);
};
return (
<Sortly items={items} onChange={handleChange}>
{props => <ItemRenderer {...props} />}
</Sortly>
);
};
const KSortableTree = kidsTree => {
const [itemsA, setItemsA] = useState(kidsTree.kidsTree);
const [positionA] = useState(kidsTree.position);
const handleChangeA = newItemsA => {
setItemsA(newItemsA);
};
return (
<Sortly items={itemsA} onChange={handleChangeA}>
{props => <ItemRendererA {...props} position={positionA} />}
</Sortly>
);
};
function FormDetail({ values, handleSubmit }) {
return (
<form onSubmit={handleSubmit}>
<h3>Family Tree</h3>
<DndProvider backend={HTML5Backend}>
<ContextProvider>
<PSortableTree parentTree={values.family.parents} />
</ContextProvider>
</DndProvider>
<div
style={{
padding: 16,
backgroundColor: "lightgrey",
borderRadius: "8px",
marginTop: "20px",
maxWidth: "100vw"
}}
>
{JSON.stringify(values)}
</div>
</form>
);
}
function App() {
return (
<Formik
enableReinitialize
initialValues={{
family: {
id: "2da80396",
parents: [
{
depth: 0,
id: "01a3b77c",
kids: [
{
depth: "1",
id: "01a3b77d",
text: "A",
correct: true
},
{
depth: "1",
id: "02fd6f62",
text: "C",
correct: false
}
],
text: "Parent 1"
},
{
depth: 0,
id: "773a4170",
kids: [
{
depth: "1",
id: "773a4171",
text: "A",
correct: false
},
{
depth: "1",
id: "773a4172",
text: "B",
correct: true
},
{
depth: "1",
id: "773a4173",
text: "C",
correct: false
}
],
text: "Parent 2"
},
{
depth: 0,
id: "a3652131",
kids: [
{
depth: "1",
id: "1c081c33",
text: "G",
correct: false
},
{
depth: "1",
id: "a3654842",
text: "A",
correct: true
},
{
depth: "1",
id: "a3654843",
text: "B",
correct: false
}
],
text: "Parent 3"
},
{
depth: 0,
id: "a3654845",
kids: [
{
depth: "1",
id: "a3654846",
text: "A",
correct: true
},
{
depth: "1",
id: "a3654847",
text: "B",
correct: false
}
],
text: "Parent 4"
},
{
depth: 0,
id: "eb3dc4d9",
kids: [
{
depth: "1",
id: "2103b3bc",
text: "D",
correct: true
},
{
depth: "1",
id: "28650f35",
text: "A",
correct: false
},
{
depth: "1",
id: "699584c2",
text: "B",
correct: false
},
{
depth: "1",
id: "a9edd5c4",
text: "C",
correct: false
}
],
text: "Parent 5"
}
],
text: "Heading"
}
}}
onSubmit={values => alert(JSON.stringify(values))}
component={FormDetail}
/>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
This is my code:
import React, { useState, useEffect } from 'react';
import { Fade } from "#material-ui/core";
import MaterialTable from 'material-table';
import { makeStyles } from '#material-ui/core/styles';
import './styles.css';
const useStyles = makeStyles(theme => ({
root: {
flexGrow: 1,
width: '70%',
margin: 'auto',
marginTop: 20,
boxShadow: '0px 0px 8px 0px rgba(0,0,0,0.4)'
}
}));
function User(props) {
const classes = useStyles();
const [checked, setChecked] = React.useState(false);
useEffect(() => {
setChecked(prev => !prev);
}, [])
const [state, setState] = React.useState({
columns: [
{ title: 'name', field: 'name' },
{ title: 'Setor', field: 'sector' }
],
data: [
{ name: 'Tom Brady', setor: 'Quarterback'},
{ name: 'Aaron Rodgers', setor: 'Quarterback'},
{ name: 'Ryan Tannehill', setor: 'Quarterback'},
{ name: 'Julian Edelman', setor: 'Wide Receiver'},
{ name: 'Julio Jones', setor: 'Wide Receiver'},
{ name: 'Marcus Mariota', setor: 'Quarterback'},
{ name: 'Patrick Mahomes', setor: 'Quarterback'},
{ name: 'Antonio Brown', setor: 'Wide Receiver'},
{ name: 'Eli Manning', setor: 'Quarterback'},
{ name: 'Antonio Brown', setor: 'Wide Receiver'},
{ name: 'Mike Evans', setor: 'Wide Receiver'},
{ name: 'Russel Wilson', setor: 'Quarterback'},
{ name: 'Drew Brees', setor: 'Quarterback'},
{ name: 'Cam Newton', setor: 'Quarterback'}
],
actions: [
{ icon: 'create', tooltip: 'Edit', onClick: (event, rowData) => alert('Edit ' + rowData.name + '?')},
{ icon: 'lock', tooltip: 'Block', onClick: (event, rowData) => alert('Block ' + rowData.name + '?')},
{ icon: 'delete', tooltip: 'Delete', onClick: (event, rowData) => alert('Delete ' + rowData.name + '?')}
],
options: {
headerStyle: { color: 'rgba(0, 0, 0, 0.54)' },
actionsColumnIndex: -1,
exportButton: true,
paging: true,
pageSize: 10,
pageSizeOptions: [],
paginationType: 'normal'
}
});
return (
<>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap" />
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons" />
<Fade in={checked} style={{ transitionDelay: checked ? '300ms' : '0ms' }}>
<div className={classes.root}>
<MaterialTable options={state.options} title="Users" columns={state.columns} data={state.data} actions={state.actions}></MaterialTable>
</div>
</Fade>
</>
);
}
export default User;
I wanna add this button:
If I follow the default code from here https://material-ui.com/pt/components/tables/, I must add this code:
editable={{
onRowAdd: newData =>
new Promise(resolve => {
setTimeout(() => {
resolve();
setState(prevState => {
const data = [...prevState.data];
data.push(newData);
return { ...prevState, data };
});
}, 600);
}),
But this code calls a specific function for material-table, I wanna call my own function, how can I add the previous button and call my own function?
My own function will open a modal with some inputs, more inputs than I show on table.
You can create custom actions
<MaterialTable
title="Editable Example"
columns={state.columns}
data={state.data}
actions={[
{
icon: "add_box",
tooltip: "my tooltip",
position: "toolbar",
onClick: () => {
console.log("clicked");
}
}
]}
/>
Working demo: https://codesandbox.io/s/material-demo-mgh26
You can override the toolbar, adding your custom button (or some other content!), as explained at https://stackoverflow.com/a/69854673/1288109 :
<MaterialTable
components={{
Toolbar: (props) => (
<div
style={{
display: "flex",
justifyContent: "flex-end",
alignItems: "center"
}}
>
<div style={{ width: "13rem" }}>
<MTableToolbar {...props} />
</div>
<Tooltip title="Add">
<IconButton>
<AddBox />
</IconButton>
</Tooltip>
</div>
),
}}
/>
You can use the position or isFreeAction property for having the action displayed there.
<MaterialTable
title="Editable Example"
columns={state.columns}
data={state.data}
actions={[
{
icon: "add_box",
tooltip: "my tooltip",
isFreeAction: true,
onClick: () => {
console.log("clicked");
}
}
]}
/>
The position parameter is more flexible providing different placements for the Button.
isFreeAction in the other hand accepts just a boolean for the action type.
Sandbox cloned from Mosh Feu https://codesandbox.io/s/material-demo-m8eug
How can I copy rows and table content in react ? im using antd library however when i copy the table rows and contents and paste using react-copy -to clipboard currently table data is being store in json this.state.datasource but when i copy i just get [object Object],[object Object] instead of actuall row and column data , can someone pls help thanks!
/*eslint-disable */
import React, { Component } from 'react'
import { Table, Input, Button, Popconfirm, Form } from 'antd'
import { Helmet } from 'react-helmet'
import { Link } from 'react-router-dom'
import { connect } from 'react-redux'
import { Menu, Icon } from 'antd';
import {CopyToClipboard} from 'react-copy-to-clipboard';
import styles from './style.module.scss'
const EditableContext = React.createContext();
const EditableRow = ({ form, index, ...props }) => (
<EditableContext.Provider value={form}>
<tr {...props} />
</EditableContext.Provider>
);
const { SubMenu } = Menu;
const EditableFormRow = Form.create()(EditableRow);
class EditableCell extends React.Component {
state = {
editing: false,
copied: false,
};
onCopy() {
console.log("copied");
alert('copied to clipboard');
}
renderCell = form => {
this.form = form;
const { children, dataIndex, record, title } = this.props;
const { editing } = this.state;
return editing ? (
<Form.Item style={{ margin: 0 }}>
{form.getFieldDecorator(dataIndex, {
rules: [
{
required: true,
message: `${title} is required.`,
},
],
);
};
render() {
const {
editable,
dataIndex,
title,
record,
index,
handleSave,
children,
...restProps
} = this.props;
return (
<td {...restProps}>
{editable ? (
<EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>
) : (
children
)}
</td>
);
}
}
class Campaign extends React.Component {
constructor(props) {
super(props);
this.columns = [
{
title: 'id',
dataIndex: 'id',
},
{
title: 'Campaign Name',
dataIndex: 'name',
editable: true,
},
{
title: 'Banners',
dataIndex: 'address',
editable: true,
},
{
title: 'Video',
dataIndex: 'Video',
editable: true,
},
{
title: 'Target',
dataIndex: 'Target',
editable: true,
},
{
title: 'Exchanges',
dataIndex: 'Exchanges',
editable: true,
},
{
title: 'Status',
dataIndex: 'Status',
editable: true,
},
{
title: 'Delete',
dataIndex: 'Banners',
render: (text, record) =>
this.state.dataSource.length >= 1 ? (
<Popconfirm title="Sure to delete?" onConfirm={() => this.handleDelete(record.key)}>
<a style={{color:'blue'}} href="javascript:;">Delete</a>
</Popconfirm>
) : null,
},
];
this.state = { //table data i want to copy
dataSource: [
{
key: '0',
name: 'Kates Campaign',
id: '32',
Video: 'London, Park Lane no. 0',
Target: 'bacon',
Exchanges: 'Eggs',
},
{
key: '1',
name: 'Fyber Tests',
id: '32',
address: 'Sample Banner Ad (ID 6 ECPM 20.0) ',
},
],
count: 2,
};
}
render() {
const { dataSource } = this.state;
const components = {
body: {
row: EditableFormRow,
cell: EditableCell,
},
};
const columns = this.columns.map(col => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: record => ({
record,
editable: col.editable,
dataIndex: col.dataIndex,
title: col.title,
handleSave: this.handleSave,
}),
};
});
return (
<div>
<br></br>
<h1> Campaigns </h1>
<br></br><br></br>
<Menu
className={styles.menu}
onClick={this.handleClick}
style={{ marginleft: 80}}
defaultSelectedKeys={['1']}
defaultOpenKeys={['sub1']}
mode="inline"
>
<SubMenu className={styles.sub}
key="sub4"
title={
<span>
<Icon type="setting"style={{
color: '#8c54ff'}} />
<span className={styles.title}>Options</span>
</span>
}
>
<span className={styles.icon}> <Icon type="arrow-down" style={{
color: '#8c54ff'}} /></span>
<Menu.Item key="9"> CSV</Menu.Item>
<span className={styles.icon}><Icon type="sync" style={{
color: '#8c54ff'}}/> </span>
<Menu.Item key="11"> Sync</Menu.Item>
<span className={styles.icon}>
<Icon
type="copy"
style={{
color: '#8c54ff',
}}
/>
</span>// this is function to copy table data
<CopyToClipboard text={dataSource} onCopy={() => this.setState({copied: true})}>
</SubMenu>
</Menu>
<br></br>
);
}
}
export default Campaign