0

My app hides the file input and uses the Label as a button.

I render the selected file name with an (x) button so the input can be cleared.

I am trying to use a ref to target the input.

On click of the (x), it appears that the input is cleared, but the form does not sense the change, and therefore my submit button remains enabled, which it should not, as the file input is required.

I feel like refs are the right way to do this, but I would appreciate help getting this last mile!

  • No errors currently and the
const { Button, Form, FormGroup, Label, Input, FormText } = Reactstrap

export default (props) => {
    
    
    
    const [files, updateFiles] = React.useState([])
    const [fileInputFocused, updateFocus] = React.useState(false)
    const [formIsValid, toggleSubmitButton] = React.useState(false)
    const fileInputRef = React.useRef()
    
    
    
    
    function handleFileChange(e){
        const files = e.target.files
        let filesArr = []
        for ( const file in files ) {
            filesArr.push(files[file])
        }
        updateFiles(filesArr.filter( file => file.name != undefined && file.name != 'item'))
    }
    
    
    
    function removeFile(e) {
        // updateFiles(files.filter( file => file.name != e.currentTarget.id))
        updateFiles([])
        fileInputRef.current.value = ''
        **---> EXPECTED CHANGE EVENT TO FIREE HERE <----**
    }
    
    
    function handleFocus(e) {
        updateFocus(true)
    }
    
    
    function handleBlur(e) {
        updateFocus(false)
    }
    
    function checkValidity(e){
        e.currentTarget.checkValidity() ? toggleSubmitButton(true) : toggleSubmitButton(false)
    }
    
    
    
    function renderFilename(name){
        return (
            <div key={name} className="submit-resume__filename">
                {name}
                <button id={name} onClick={removeFile} className="btn-icon btn-icon--hover-red" type="button">
                    <span className="material-icons">cancel</span>
                </button>
            </div>
        )
    }
    
    
    
    return (
        <Form onChange={checkValidity}>
            
            <div className="text-center mb-4">
                <h6 className="text-indigo"><small>Apply Today</small></h6>
                <div className="text-darkgray text-bold">Send us Your Resume</div>
            </div>
        
            <FormGroup>
                <Label for="fullName">FULL NAME</Label>
                <Input required type="text" name="full_name" id="fullName" placeholder="" />
            </FormGroup>
            
            <FormGroup>
                <Label for="email">EMAIL ADDRESS</Label>
                <Input required type="email" name="email" id="email" placeholder="" />
            </FormGroup>
              
            <FormGroup>
                <Label for="file" className={`btn btn-choose-file js-labelFile mb-0 d-block ${ fileInputFocused ? 'focused' : '' } `}>
                    <span className="js-fileName mr-1">Choose a file</span>
                    <span className="material-icons">file_present</span>
                </Label>
                <Input required ref={fileInputRef} type="file" accept=".doc,.docx,.pdf" name="file" id="file" onFocus={handleFocus} onBlur={handleBlur} onChange={handleFileChange} className="input-file" />
                <div>
                    {files.map(file => renderFilename(file.name))}
                </div>
            </FormGroup>
            
            <FormGroup>
                <Button disabled={ !formIsValid ? true : false } className="btn btn-curio d-block w-100" type="submit" name="submit" id="submit" placeholder="Submit">
                    Submit My Resume <span className="material-icons">east</span>
                </Button>
            </FormGroup>
            
        </Form>
    );
    
}

Zach
  • 87
  • 8

1 Answers1

1

This is an old question, but I was working on something similar. You can handle it in a few ways it seems. You can dispatch a custom event on your ref using the following link:

What is the best way to trigger onchange event in react js

You could also refactor so that your file change is something like this:

function handleFileChange(e) {
  const files = e.target.files
}

function handleFiles(files) {
  let filesArr = []
  for ( const file in files ) {
    filesArr.push(files[file])
  }
  updateFiles(filesArr.filter( file => file.name != undefined && file.name != 'item'))
}

and then in your removeFile method just call handleFiles([]) or something like that.

While the first section is probably the more "right" way of doing things, note that either of these are probably not exactly what you're looking for.

Perhaps a better solution overall would be to dispatch an event to your ref with an empty list in the files instead of manually modifying it.

ice1080
  • 314
  • 3
  • 9