1

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

2
  • where is exactly the p-button p-component p-button-icon-only element? is it inside your react components hierarchy? Commented Jan 3, 2022 at 21:35
  • @Heartbit If you select a file using Choose button and right click on the selected file to inspect it, you will see that. Please see this image screenshot with Inspect thing on Firefox : i.sstatic.net/P8mwB.png Commented Jan 3, 2022 at 21:41

4 Answers 4

1

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>
  );
Sign up to request clarification or add additional context in comments.

11 Comments

Thank you!. One question - where should I set the property(inputFileType.disabled = false;) inside itemTemplate function which I set to true inside onTemplateAdvancedSelect function?
I think I can do the following inside onTemplateRemove() function, like the following: ` const onTemplateRemove = (file, callback) => { // setTotalSize(totalSize - file.size); let inputFileType = document.querySelector("input[type=file]"); inputFileType.disabled = false; callback(); };`
For some reason, it's not getting enabled again in my code after I used it like I mentioned in my comment above.
you should pass ref and do dom manipulation with that reference
Sorry I am little confused. The button seems to be getting disabled after using domeInput.disabled = true. However, I am wondering Where would I put ` const domeInput = fileUploadRef.current.fileInput; domeInput.disabled = false;` to enable it once user hit the cross icon of the button? Thanks!
|
0

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>
    </>
  );
}

1 Comment

Can you answer in the context of my question? refs came to my mind but I am not sure how to use it to grab a button element which gets created on the fly and then work on it. Thanks
0

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.

6 Comments

Do you want to remove the image from the upload stack by clicking the x button? Yes, and while doing that I want to set inputFileType.disabled to false since it has been set to true inside onTemplateAdvancedSelect function when a user clicked the Choose button and selected a file.
Can you explain via code - how to use ref on p-button p-component p-button-icon-only inside onTemplateRemove ?
Ideally, you would use useRef but since you don't have access to input[type=file] it's ok to use querySelector. You can contribute to the lib to have a prop that is setting the input type to disabled.
Could you elaborate on You can contribute to the lib to have a prop that is setting the input type to disabled. ? Thanks !
I see there is a disabled property. I guess that's setting the input filed to disabled. Why don't you use that instead of imperatively setting the disabled property?
|
0

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)}
    />

3 Comments

This seems to be not working since I have set ` inputFileType.disabled = true;` inside onTemplateAdvancedSelect function. Please let me know if there is another way of handling my goal.Thanks!
I've tested in the sandbox you've shared and this worked fine. Please have a look again.
Thanks. I think you were setting setDisableButton(true) somewhere in onTemplateAdvancedSelect function because I don't think I am using it anywhere in my sandbox even though i have declared it? One problem with this approach is that as soon as I select a file, it disables all the three buttons so a user won't be able to upload the selected file if he wants to. If you could share your version of modified sandbox with your solution, that would be great.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.