Reputation: 2539
Let's say I have a list of customers, and I show them in a tabular format.
I can add some icons to the end of each customer row, to let user manage each row. Typical icons are delete and edit and icons like that.
Now I want to add an icon/action, that opens a dialog, passes some data from the row to the dialog, and gets data back from the dialog when it's closed.
In Angular, I would do it very easily. Because I could programmatically call a showDialog
method or something similar to it, and pass parameters to it, and get the results. It's very dynamic.
In react + Material UI however, I'm stuck.
I want to render a dialog, and on the click of action of each row, I want to show that dialog and pass the data to it, and get data back from it.
What is the proper way of doing it?
Upvotes: 1
Views: 3993
Reputation: 3405
The minimal requirements are:
Here's a sample made with react, mui,and typescript
Define sample data and type
const tablesData = [
{ customerId: 1, customerName: 'customer1', address: 'some address 1' },
{ customerId: 2, customerName: 'customer2', address: 'some address 2' },
{ customerId: 3, customerName: 'customer3', address: 'some address 3' },
{ customerId: 4, customerName: 'customer4', address: 'some address 4' },
{ customerId: 5, customerName: 'customer5', address: 'some address 5' },
];
type Customer = typeof tablesData[number];
Defined a dialog component that can display an address of the customer which can be editable and submitted to the API later on if you want
interface EditCustomerDialogProps {
open: boolean,
closeHandler: () => void,
customer: Customer,
onSave: (customer: Customer) => void,
}
function EditCustomerDialog(props: EditCustomerDialogProps) {
const { open, closeHandler, customer, onSave } = props;
useEffect(function onCustomerChangeUpdateFormValues() {
setAddress(customer.address);
}, [customer]);
const [address, setAddress] = useState('');
const addressChangeHandler = useCallback(function _addressChangeHandler(event: any) {
setAddress(event.target.value);
}, []);
const saveHandler = useCallback(function _saveHandler() {
onSave({
...customer,
address, // editable info,
});
closeHandler();
}, [address]);
return (
<Dialog open={open} onClose={closeHandler}>
<DialogTitle>
{'Edit customer info'}
</DialogTitle>
<DialogContent dividers>
<TextField
placeholder="address"
value={address}
onChange={addressChangeHandler}
/>
</DialogContent>
<DialogActions>
<Button onClick={saveHandler}>
{'Save'}
</Button>
<Button onClick={closeHandler}>
{'Cancel'}
</Button>
</DialogActions>
</Dialog>
);
}
The parent component that controls the Dialog and can possible calls the API on save
function ComponentXYZ() {
const [openEditDialgo, setOpenEditDialog] = useState(false);
const closeDialogHandler = useCallback(function _handleClose() {
setOpenEditDialog(false);
}, []);
const [selectedCustomer, setSelectedCustomer] = useState<Customer>({
customerId: 0,
customerName: '',
address: '',
});
function customerEditHandler(customer: any) {
setSelectedCustomer({ ...customer });
setOpenEditDialog(true);
}
const saveHandler = useCallback(function _saveHandler(customer: Customer) {
console.log({ customer });
}, []);
return (
<Fragment>
<EditCustomerDialog
open={openEditDialgo}
closeHandler={closeDialogHandler}
customer={selectedCustomer}
onSave={saveHandler}
/>
<div>
{
tablesData.map(customer => (
<Stack
key={customer.customerId}
direction="row">
<Typography>
{customer.customerName}
</Typography>
<Button onClick={() => customerEditHandler(customer)}>
{'edit info'}
</Button>
</Stack>
))
}
</div>
</Fragment>
);
}
Upvotes: 5