React/Custom form
Loading live demo…from dhtmlx.github.io
React
Custom form
Replace the default task editor with a draggable Material UI modal form.
- Demo.tsx
- EditorModal.tsx
src/examples/custom-form/Demo.tsx View on GitHub
import { useEffect, useRef } from 'react';
import ReactGantt from "@dhtmlx/trial-react-gantt";
import "@dhtmlx/trial-react-gantt/dist/react-gantt.css";
import CustomLightbox from "./EditorModal";
export default function BasicInitDemo() {
const ganttRef = useRef(null);
useEffect(() => {
document.title = "DHTMLX React Gantt | Custom Form";
}, []);
const tasks = [
{ id: 1, text: "Office itinerancy", type: "project", progress: 0.4, open: true, start_date: "02-04-2025 00:00", duration: 17, parent: 0 },
{ id: 2, text: "Office facing", type: "project", start_date: "02-04-2025 00:00", duration: 5, progress: 0.6, parent: 1, open: true },
{ id: 5, text: "Interior office", type: "task", start_date: "02-04-2025 00:00", duration: 3, parent: 2, progress: 0.6, open: true },
{ id: 6, text: "Air conditioners check", type: "task", start_date: "05-04-2025 00:00", duration: 2, parent: 2, progress: 0.29, open: true },
{ id: 3, text: "Furniture installation", type: "project", start_date: "08-04-2025 00:00", duration: 2, parent: 1, progress: 0.6, open: false },
{ id: 7, text: "Workplaces preparation", type: "task", start_date: "08-04-2025 00:00", duration: 2, parent: 3, progress: 0.6, open: true }
];
const links = [
{ id: 1, source: "2", target: "3", type: "0" },
];
useEffect(() => {
//const gantt = ganttRef.current?.instance;
}, []);
return (
<div className="demo-container">
<title>DHTMLX React Gantt | Custom Edit Form</title>
<ReactGantt
ref={ganttRef}
tasks={tasks}
links={links}
customLightbox={<CustomLightbox />}
/>
</div>
);
}
src/examples/custom-form/EditorModal.tsx View on GitHub
import React, { useState } from 'react';
import Button from "@mui/material/Button";
import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
import Paper from '@mui/material/Paper';
import Draggable from 'react-draggable';
export interface CustomLightboxProps {
data?: any;
onSave?: (task: any) => void;
onCancel?: () => void;
onDelete?: () => void;
}
const CustomLightbox: React.FC<CustomLightboxProps> = ({
data,
onSave,
onCancel,
onDelete
}) => {
let updatedTaskText = data.text || "";
const handleSaveClick = () => {
if(onSave)
onSave({ ...data, text: updatedTaskText });
};
function PaperComponent(props: any) {
const nodeRef = React.useRef(null);
return (
<Draggable
nodeRef={nodeRef}
handle="#draggable-dialog-title"
cancel={'[class*="MuiDialogContent-root"], input,textarea'}
>
<Paper {...props} ref={nodeRef}/>
</Draggable>
);
}
function TextComponent() {
const [description, setDescription] = useState<string>(data.text || '');
return (
<TextField
id="task_text"
hiddenLabel
multiline
value={description}
autoFocus
onChange={(e) => {
updatedTaskText = e.target.value;
setDescription(e.target.value)
}}
sx={{ width: '100%', padding: '8px', marginTop: '10px' }}
/>
)
}
return (
<Dialog
open={true}
PaperComponent={PaperComponent}
aria-labelledby="draggable-dialog-title"
className="lightbox"
onClose={onCancel}
>
<DialogTitle style={{ cursor: 'move' }} id="draggable-dialog-title">
Edit Task
</DialogTitle>
<DialogContent>
<DialogContentText id="alert-dialog-description">
Description
</DialogContentText>
<TextComponent />
<DialogActions className='buttons'>
<Button variant="contained" onClick={handleSaveClick}>Save</Button>
<Button variant="contained" onClick={onCancel}>Cancel</Button>
<Button variant="contained" onClick={onDelete}>Delete</Button>
</DialogActions>
</DialogContent>
</Dialog>
);
};
export default CustomLightbox;