React way of grabbing a button element and using disable property

645 views Asked by At

I have the following code where a user can select a file and hit upload and the Choose button is disabled.

Code Sanbox link is here:

 import "primeicons/primeicons.css";
    import "primereact/resources/themes/lara-light-indigo/theme.css";
    import "primereact/resources/primereact.css";
    import "primeflex/primeflex.css";
    import "../../index.css";
    import ReactDOM from "react-dom";
    
    import React, { useRef, useState } from "react";
    import { FileUpload } from "primereact/fileupload";

export const FileUploadDemo = () => {
  const toast = useRef(null);
  const [disableButton, setDisableButton] = useState(false);

  const onUpload = () => {
    toast.current.show({
      severity: "info",
      summary: "Success",
      detail: "File Uploaded"
    });
  };

  const onTemplateAdvancedSelect = (e) => {
    console.log("Printing onTemplateAdvancedSelect ");
    console.log(e);
    let inputFileType = document.querySelector("input[type=file]");
    //setDisableButton(true);
    inputFileType.classList.add("toDisableOnSelect");
    inputFileType.disabled = true;

    let htmlCollection = document.getElementsByClassName(
      "p-button p-component p-button-icon-only"
    );
    console.log("Printing htmlCollection");
    console.log(htmlCollection.length);
    console.log(htmlCollection);

    // htmlCollection.addEventListener("click", function () {
    //   inputFileType.disabled = false;
    // });
    //console.log(htmlCollection.item(19));
  };

  return (
    <div>
      <div className="card">
        <h5>Advanced</h5>
        <FileUpload
          multiple={false}
          name="demo[]"
          url="https://primefaces.org/primereact/showcase/upload.php"
          onUpload={onUpload}
          id={"myId"}
          accept="image/*"
          maxFileSize={1000000}
          onSelect={onTemplateAdvancedSelect}
          disabled={disableButton}
          emptyTemplate={
            <p className="p-m-0">Drag and drop files to here to upload.</p>
          }
        />
      </div>
    </div>
  );
};

const rootElement = document.getElementById("root");
ReactDOM.render(<FileUploadDemo />, rootElement);

So Inside onTemplateAdvancedSelect function, I want to set inputFileType.disabled to false once user hits the cross icon as shown below:

enter image description here

I don't want to use getElementByClassName just like I have attempted to use in my code of above function. What would be a better way to achieve my goal?

Primereact version I'm using : 4.2.2

4

There are 4 answers

11
Heartbit On BEST ANSWER

One solution is customizing the row item of the selected file. so the itemTemplate prop is exactly for that goal.

export const FileUploadDemo = () => {
  const toast = useRef(null);
  const fileUploadRef = useRef(null) // reference to uploader node
  const [disableButton, setDisableButton] = useState(false);
  const onTemplateRemove = (file, callback) => {
        // setTotalSize(totalSize - file.size);
        const domInput = fileUploadRef.current.fileInput;
        domInput.disabled = false;
        callback();
  }
  const onTemplateAdvancedSelect = () => {
     const domInput = fileUploadRef.current.fileInput; // pure dome element
     domInput.disabled = true;
     
  }
  const itemTemplate = (file, props) => {
        return (
            <>
            <div>
                <img alt={file.name} role="presentation" src={file.src} width="50" />

            </div>
            <div class="p-fileupload-filename">{file.name}</div>
            <div>{file.size}</div>
            <div>
                { /* here you have access to that button */}
                <button
                  type="button"
                  class="p-button p-component p-button-icon-only"
                  onClick={() => onTemplateRemove(file, props.onRemove)}>
                    <span class="p-button-icon p-c pi pi-times"></span>
                    <span class="p-button-label p-c">&nbsp;</span>
                </button>
            </div>
            </>
        )
    }
  return (
    <div>
      <div className="card">
        <h5>Advanced</h5>
        <FileUpload
          ref={fileUploadRef} // pass a reference for `input` manipulation
          multiple={false}
          name="demo[]"
          url="https://primefaces.org/primereact/showcase/upload.php"
          onUpload={onUpload}
          id={"myId"}
          accept="image/*"
          maxFileSize={1000000}
          /* here we should pass the customized template as prop */
          itemTemplate={itemTemplate} 
          onSelect={onTemplateAdvancedSelect}
          disabled={disableButton}
          emptyTemplate={
            <p className="p-m-0">Drag and drop files to here to upload.</p>
          }
        />
      </div>
    </div>
  );
1
Prateek On

Please use useRef hook provided by react. Example below:

function TextInputWithFocusButton() {
  const inputEl = useRef(null);
  const onButtonClick = () => {
    // `current` points to the mounted text input element
    inputEl.current.focus();
  };
  return (
    <>
      <input ref={inputEl} type="text" />
      <button onClick={onButtonClick}>Focus the input</button>
    </>
  );
}
3
Sam On

You don't need to do a getElementsByClassName. You can use the onRemove event to handle the file remove event.

<FileUpload
      multiple={false}
      name="demo[]"
      url="https://primefaces.org/primereact/showcase/upload.php"
      onUpload={onUpload}
      id={"myId"}
      accept="image/*"
      maxFileSize={1000000}
      onSelect={onTemplateAdvancedSelect}
      disabled={disableButton}
      emptyTemplate={
        <p className="p-m-0">Drag and drop files to here to upload.</p>
      }
      onRemove={(e, file) => setDisableButton(false)}
    />
6
Gábor Ottlik On

I'm trying to understand your use case. Do you want to remove the image from the upload stack by clicking the x button?

I think you should rather use the built-in API to trigger functionality. If that doesn't help you can extend the library.