5

A user can upload multiple images in the website. Users can delete an image, this was solved easily because of a function provided by the antd. But there is no certain function to update the existing image in the list of images. Like the image that the user wants to update, should be deleted and then the new selected image gets placed at that old image's position.

This is my AntD Upload Component:

<ImageUpload
    uploadProps={{
      ...uploadProps,
      name: name,
      accept: "image/*",
      listType: 'picture',
      className: 'avatar-uploader bg-black',
      showUploadList: showUploadList,
      itemRender: (originNode, file, fileList, actions) => {
        console.log(actions)
        return (
          <ImagePreview key={file.uid} title={file.name} size={file.size} type={file.type} imageUrl={file.thumbUrl} deleteButton={actions.remove} />
        );
      }
    }}
    title={title}
    uploadButtonText={buttonText}
    uploadButtonStyle={{ height: 100 }}
    uploadButtonIcon={<ImageIcon style={{ fontSize: 30 }} />}
    uploadWrapperStyle={{ width: width }}
    showUploadButton={showUploadButton}
  />

Here's my <ImageUpload /> Component:

onst ImageUpload = ({
  // Uploader props
  uploadProps,
  uploadWrapperStyle,

  // Button props
  title,
  uploadingImage,
  uploadButtonIcon,
  uploadButtonText,
  uploadButtonStyle = {},
  onClick = () => {},
  showUploadButton,

  // Other props
  loading,
  skeletonHeight
}) => {
  const [showImageViewer, setShowImageViewer] = useState(false)
  const [imagesToCarousel, setImagesToCarousel] = useState([])
  const [localFileList, setLocalFileList] = useState([])

  const { fileList } = uploadProps
  console.log('image');
  const getBase64 = (file) =>
    new Promise((resolve, reject) => {
      const reader = new FileReader()
      reader.readAsDataURL(file)
      reader.onload = () => {
        resolve(reader.result)
      }
      reader.onerror = (error) => reject('FR error', error)
    })

  useEffect(() => {
    if (fileList) {
      const imagesToSet = fileList
        .filter((file) => (file.type ? !file.type.includes('pdf') : true))
        .map(async (image) => {
          let tmpItem = { ...image }
          if (!tmpItem.url) {
            const objUrl = await getBase64(image.originFileObj)
            tmpItem = createUploadFileList(objUrl, false)
          }

          return tmpItem.url
        })

      Promise.all(imagesToSet).then((completed) => {
        setImagesToCarousel(completed)
      })
    }
  }, [fileList])

  useEffect(() => {
    setLocalFileList(fileList || [])
  }, [fileList])

  const uploadButton = () => (
    <ImageUploadButtonWithThumbnail
      uploadingImage={uploadingImage}
      uploadButtonIcon={uploadButtonIcon}
      uploadButtonText={uploadButtonText}
      uploadButtonStyle={uploadButtonStyle}
      onClick={onClick}
      // image={images}
    />
  )

  return (
    <UploadWrapper style={uploadWrapperStyle || {}}>
      {loading ? (
        <Skeleton height={skeletonHeight} />
      ) : (
        <>
          {title && <H7>{`${title}:`}</H7>}

          <CustomUpload
            fileList={localFileList}
            {...uploadProps}
            // onPreview={() => setShowImageViewer(true)}
          >
            {showUploadButton ? uploadButton() : null}
          </CustomUpload>

           <Modal
                  visible={showImageViewer}
                  footer={null}
                  onCancel={() => setShowImageViewer(false)}
                  centered
                  width='70%'
                  bodyStyle={{ height: '70vh', overflow: 'hidden' }}
                >
                  <ImageCarousel images={imagesToCarousel} />
                </Modal>
        </>
      )}
    </UploadWrapper>
  )
}

This is my ImagePreview Compoenent:

<div key={key} className="flex flex-wrap gap-4 sm:items-center p-4 border border-dashed m-4 rounded-lg">
            <img className="h-[144px] w-[195px]" src={imageUrl} alt="" />
            <div className="flex flex-col gap-8">
                <div>
                    <h3 className="text-base">{title || 'Image Title'}</h3>
                    <div className="flex items-center gap-2 sm:gap-4 text-xs text-[#2E2B2EB2] opacity-75 mt-2">
                        <p className='mb-0'>{imgType?.map(char => <span className='uppercase'>{char}</span>) || 'Image Type'}</p>
                        <svg width="4" height="5" viewBox="0 0 4 5" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <circle cx="2" cy="2.5" r="2" fill="#2E2B2E" fillOpacity="0.3" />
                        </svg>
                        <p className='mb-0 uppercase'>{size / 1000 + ' Kb' || 'Image Size'}</p>
                    </div>
                </div>
                <div className="flex gap-4 w-full">
                    <button className="flex items-center gap-2 rounded-md border border-[#2E2B2EB2] text-sm px-3 py-1 justify-center">
                        <svg width="12" height="15" viewBox="0 0 12 15" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M3.50033 11.3333H8.50033V6.33333H11.8337L6.00033 0.5L0.166992 6.33333H3.50033V11.3333ZM0.166992 13H11.8337V14.6667H0.166992V13Z" fill="#2E2B2E" />
                        </svg>
                        <span>Update</span>
                    </button>
                    <button onClick={deleteButton} className="flex items-center gap-2 rounded-md border border-[#2E2B2EB2] text-sm px-3 py-1 justify-center">
                        <svg width="12" height="15" viewBox="0 0 12 15" fill="none" xmlns="http://www.w3.org/2000/svg">
                            <path d="M3.50033 11.3333H8.50033V6.33333H11.8337L6.00033 0.5L0.166992 6.33333H3.50033V11.3333ZM0.166992 13H11.8337V14.6667H0.166992V13Z" fill="#2E2B2E" />
                        </svg>
                        <span>Delete</span>
                    </button>
                </div>
            </div>
        </div>
Burhan
  • 324
  • 2
  • 12

0 Answers0