Display Image in a Material-UI Dialog after clicking an IconButton of the ImageListItemBar

22 Views Asked by At
import * as React from 'react';
import Box from '@mui/material/Box';
import ImageList from '@mui/material/ImageList';
import ImageListItem from '@mui/material/ImageListItem';
import ImageListItemBar from '@mui/material/ImageListItemBar';
import IconButton from '@mui/material/IconButton';
import VisibilityIcon from '@mui/icons-material/Visibility';
import Dialog from '@mui/material/Dialog';
  
export default function MasonryImageList({ data }) {
  const itemData = data.map((image) => {
    return {
      img: image.url,
      title: image.titre
    }
  })
    
  return (
    <Box id='Mansonry'>
      <ImageList variant="masonry" cols={3} gap={8}>
        {itemData.map((item, index) => (
          <>
            <ImageListItem key={item.img}>
              <img
                srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
                src={`${item.img}?w=248&fit=crop&auto=format`}
                alt={item.title}
                loading="lazy"
              />
              <ImageListItemBar
                title={item.title}
                actionIcon={
                  <IconButton
                    sx={{ color: 'rgba(255, 255, 255, 0.54)' }}
                    aria-label={`Agrandir ${item.title}`}
                    onClick={() => {
                      **//When clicked, display the image on the MUI Dialog**
                    }}
                  >
                    <VisibilityIcon />
                  </IconButton>
                }
              />
            </ImageListItem>
            <Dialog onClose={handleClose} open={open}> **//How should i handle the opening and closing of each Dialog for each Image ?**
              <img src={`${item.img}`} alt={item.title}
                loading="lazy" />
            </Dialog>
          </>
        ))}
      </ImageList>
    </Box>
  );
}

The idea is to display the image on front of the screen when the IconButton is clicked. But as I have multiple images, I'm struggling with the onClose and open props of the Dialog component.

1

There are 1 best solutions below

0
Drew Reese On BEST ANSWER

You could add a selectedItem state that is either null to hide the dialogs, or a specific item to display that item's dialog. The handleClose would reset the selectedItem back to null.

Example:

export default function MasonryImageList({ data }) {
  const [selectedImg, setSelectedImg] = React.useState(null);

  const handleClose = () => setSelectedImg(null);
    
  return (
    <Box id='Mansonry'>
      <ImageList variant="masonry" cols={3} gap={8}>
        {data.map((item) => (
          <React.Fragment key={item.img}>
            <ImageListItem>
              <img
                srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
                src={`${item.img}?w=248&fit=crop&auto=format`}
                alt={item.title}
                loading="lazy"
              />
              <ImageListItemBar
                title={item.title}
                actionIcon={
                  <IconButton
                    sx={{ color: 'rgba(255, 255, 255, 0.54)' }}
                    aria-label={`Agrandir ${item.title}`}
                    onClick={() => {
                      setSelectedImg(item.img);
                    }}
                  >
                    <VisibilityIcon />
                  </IconButton>
                }
              />
            </ImageListItem>
            <Dialog
              onClose={handleClose}
              open={item.img === selectedImg}
            >
              <img
                src={item.img}
                alt={item.title}
                loading="lazy"
              />
            </Dialog>
          </React.Fragment>
        ))}
      </ImageList>
    </Box>
  );
}

You could also refactor the code a bit to render only a single Dialog.

Example:

export default function MasonryImageList({ data }) {
  const [selectedItem, setSelectedItem] = React.useState(null);

  const handleClose = () => setSelectedItem(null);
    
  return (
    <Box id='Mansonry'>
      <ImageList variant="masonry" cols={3} gap={8}>
        {data.map((item) => (
          <ImageListItem key={item.img}>
            <img
              srcSet={`${item.img}?w=248&fit=crop&auto=format&dpr=2 2x`}
              src={`${item.img}?w=248&fit=crop&auto=format`}
              alt={item.title}
              loading="lazy"
            />
            <ImageListItemBar
              title={item.title}
              actionIcon={
                <IconButton
                  sx={{ color: 'rgba(255, 255, 255, 0.54)' }}
                  aria-label={`Agrandir ${item.title}`}
                  onClick={() => {
                    setSelectedItem(item);
                  }}
                >
                  <VisibilityIcon />
                </IconButton>
              }
            />
          </ImageListItem>
        ))}
      </ImageList>
      <Dialog
        onClose={handleClose}
        open={!!selectedItem}
      >
        <img
          src={selectedItem.img}
          alt={selectedItem.title}
          loading="lazy"
        />
      </Dialog>
    </Box>
  );
}