Reputation: 14108
Goal:
Get data and display it in the dialog by using the button that is located in the column Button. In other words, you click one of the buttons and data will be displayed in the dialog.
Problem:
Today, I can only get the data by hard coding a single data but if you need to use the single dialog with different url, you probably need to code in a different approach. Please take account that you have for instance 100 row and you need to use a single <Form id={id} />
and not using 100 of <Form id={id} />
.
I have difficult to create to make a single <Form id={id} />
in relation to many rows from the table.
Info:
*Please take account that you need to use the data from the table or you can hard code it.
*You use url 'https://jsonplaceholder.typicode.com/todos/x' but you use the number from the table as a input data in order to send it to the Form.tsx.
*My skill in react TS is beginner level in relation to hobby project.
Stackblitz:
https://stackblitz.com/edit/react-ts-dhacdg
App.tsx
import * as React from 'react';
import Button from '@mui/material/Button';
import Dialog, { DialogProps } 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 { Form } from './Form';
export default function ScrollDialog() {
const [open, setOpen] = React.useState(false);
const [scroll, setScroll] = React.useState<DialogProps['scroll']>('paper');
const [id, setId] = React.useState(0);
const handleClickOpen = (scrollType: DialogProps['scroll']) => () => {
setOpen(true);
setScroll(scrollType);
};
const handleClose = () => {
setOpen(false);
};
const descriptionElementRef = React.useRef<HTMLElement>(null);
React.useEffect(() => {
if (open) {
const { current: descriptionElement } = descriptionElementRef;
if (descriptionElement !== null) {
descriptionElement.focus();
}
}
}, [open]);
return (
<div>
<table border={0}>
<thead>
<tr>
<th>Name</th>
<th>Input Data</th>
<th>Button</th>
</tr>
</thead>
<tbody>
<tr>
<td>a</td>
<td>1</td>
<td>
<button>Get Data</button>
</td>
</tr>
<tr>
<td>b</td>
<td>2</td>
<td>
<button>Get Data</button>
</td>
</tr>
<tr>
<td>c</td>
<td>3</td>
<td>
<button>Get Data</button>
</td>
</tr>
</tbody>
</table>
<Form id={id} />
</div>
);
}
Form.tsx
import React, { useState } from 'react';
import Button from '@mui/material/Button';
import Dialog, { DialogProps } 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 useMediaQuery from '@mui/material/useMediaQuery';
import { useTheme } from '@mui/material/styles';
export const Form = ({ id }: { id: number }) => {
const [inputid, setInputid] = useState('');
const [inputTitle, setInputTitle] = useState('');
React.useEffect(() => {
async function FetchData() {
var data = await fetch(
'https://jsonplaceholder.typicode.com/todos/1'
).then((res) => {
return res.json();
});
setInputid(data.id);
setInputTitle(data.title);
}
FetchData();
}, [id]);
const [open, setOpen] = React.useState(false);
const theme = useTheme();
const [scroll, setScroll] = React.useState<DialogProps['scroll']>('paper');
const fullScreen = useMediaQuery(theme.breakpoints.down('md'));
const handleClickOpen = () => () => {
var scrollType: DialogProps['scroll'];
scrollType = 'body';
setOpen(true);
setScroll(scrollType);
};
const handleClose = () => {
setOpen(false);
};
const descriptionElementRef = React.useRef<HTMLElement>(null);
React.useEffect(() => {
if (open) {
const { current: descriptionElement } = descriptionElementRef;
if (descriptionElement !== null) {
descriptionElement.focus();
}
}
}, [open]);
return (
<div>
<button onClick={handleClickOpen()}>Get Data</button>
<Dialog
fullScreen={fullScreen}
open={open}
scroll={scroll}
aria-labelledby="scroll-dialog-title"
aria-describedby="scroll-dialog-description"
>
<DialogTitle id="scroll-dialog-title">Subscribe</DialogTitle>
<DialogContent dividers={scroll === 'paper'}>
<DialogContentText
id="scroll-dialog-description"
ref={descriptionElementRef}
tabIndex={-1}
>
{inputid}
<br />
{inputTitle}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
</DialogActions>
</Dialog>
</div>
);
};
Upvotes: 1
Views: 499
Reputation: 202676
Use the open
state of the parent App
component to toggle the Form
component opened/closed. Pass the id
to the handleClickOpen
handler to (a) set the current active id
state and (b) open the Form
component.
Example:
App
export default function App() {
const [open, setOpen] = React.useState(false);
const [scroll, setScroll] = React.useState<DialogProps["scroll"]>("paper");
const [id, setId] = React.useState(0);
const handleClickOpen = (id: number) => () => {
const scrollType: DialogProps["scroll"] = "body";
setOpen(true);
setId(id);
setScroll(scrollType);
};
const handleClose = () => {
setOpen(false);
};
const descriptionElementRef = React.useRef<HTMLElement>(null);
React.useEffect(() => {
if (open) {
const { current: descriptionElement } = descriptionElementRef;
if (descriptionElement !== null) {
descriptionElement.focus();
}
}
}, [open]);
return (
<div className="App">
<div>
<table border={0}>
<thead>
<tr>
<th>Name</th>
<th>Input Data</th>
<th>Button</th>
</tr>
</thead>
<tbody>
{[
{ name: "a", id: 1 },
{ name: "b", id: 2 },
{ name: "c", id: 3 }
].map(({ name, id }) => (
<tr>
<td>{name}</td>
<td>{id}</td>
<td>
<button onClick={handleClickOpen(id)}>Get Data</button>
</td>
</tr>
))}
</tbody>
</table>
<Form id={id} open={open} onClose={handleClose} />
</div>
</div>
);
}
Form - Declare the props interface to take also the open
and onClose
props. For the fetch
use a template string to inject the passed id
prop into the request URL.
interface FormProps {
id: number;
open: boolean;
onClose: () => void;
}
export const Form = ({ id, open, onClose }: FormProps) => {
const [inputid, setInputid] = useState("");
const [inputTitle, setInputTitle] = useState("");
React.useEffect(() => {
async function FetchData() {
try {
const res = await fetch(
`https://jsonplaceholder.typicode.com/todos/${id}`
);
const data = await res.json();
setInputid(data.id);
setInputTitle(data.title);
} catch {
// handle?
}
}
FetchData();
}, [id]);
const theme = useTheme();
const [scroll, setScroll] = React.useState<DialogProps['scroll']>('paper');
const fullScreen = useMediaQuery(theme.breakpoints.down("md"));
const handleClose = () => {
onClose();
};
const descriptionElementRef = React.useRef<HTMLElement>(null);
React.useEffect(() => {
if (open) {
const { current: descriptionElement } = descriptionElementRef;
if (descriptionElement !== null) {
descriptionElement.focus();
}
}
}, [open]);
return (
<div>
<Dialog
fullScreen={fullScreen}
open={open}
scroll={scroll}
aria-labelledby="scroll-dialog-title"
aria-describedby="scroll-dialog-description"
>
<DialogTitle id="scroll-dialog-title">Subscribe</DialogTitle>
<DialogContent dividers={scroll === "paper"}>
<DialogContentText
id="scroll-dialog-description"
ref={descriptionElementRef}
tabIndex={-1}
>
{inputid}
<br />
{inputTitle}
</DialogContentText>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
</DialogActions>
</Dialog>
</div>
);
};
Upvotes: 1