Halogen: reset file upload

I have a file upload input field in my Halogen render function. I’d like to reset this after the upload is successfully processed. In this SO post: jquery - Clearing an HTML file upload field via JavaScript - Stack Overflow - some methods are described, but I’m not sure what the easiest is with Halogen. Has anybody done this and can give the most “idiomatic” solution?

Have you tried simply to keep the input’s value attribute in component state and change this value to "" on successful upload?

I tried that now. This is my file upload:

HH.input [ 
    HP.type_ InputFile
  , HE.onFileUpload FileUpload
  , HP.value (fromMaybe "" ((\lf -> name lf) <$> state.lastFile)) 
  ]

As you can see, I have an action FileUpload in reaction to a file upload. In the action handler, I extract the first file given and store it in state.lastFile, which is of type Maybe File.

Using this code, I get the following error message on the console:

Uncaught DOMException: Failed to set the 'value' property on 'HTMLInputElement': This input element accepts a filename, which may only be programmatically set to the empty string.
    at exports.unsafeSetAny (http://localhost:1234/dev.e31bb0bc.js:58696:12)
    at http://localhost:1234/dev.e31bb0bc.js:60222:13
    at Object.exports.diffWithKeyAndIxE (http://localhost:1234/dev.e31bb0bc.js:58779:15)
    at Step.patchProp [as value2] (http://localhost:1234/dev.e31bb0bc.js:60299:37)
    at Object.step (http://localhost:1234/dev.e31bb0bc.js:58351:12)
    at Step.patchElem [as value2] (http://localhost:1234/dev.e31bb0bc.js:59594:41)
    at Object.step (http://localhost:1234/dev.e31bb0bc.js:58351:12)
    at onThese (http://localhost:1234/dev.e31bb0bc.js:59613:38)
    at Object.exports.diffWithIxE (http://localhost:1234/dev.e31bb0bc.js:58743:17)
    at Step.patchElem [as value2] (http://localhost:1234/dev.e31bb0bc.js:59624:39)

So you need to do this in foreign code. Give a RefLabel to your input component and in FileUpload handler reference this element by H.getRef:

(...)
H.getRef yourRef >>= traverse_ (liftEffect <<< removeValue)

where removeValue :: Element -> Effect Unit is a foreign function that clears the value property of an element passed as an argument.

Oh wow, so it’s a little more intricate. I’ll try and report back!

Yeah, the removeValue approach seems to be the way it needs to be done unless we can add some magic in halogen-vdom to handle this case. There’s a similar issue that can occur if patching would cause the type of an input to switch from file to something else: DOMException thrown when switching between file/text input types · Issue #28 · purescript-halogen/purescript-halogen-vdom · GitHub

Another approach that might work here is if you use keyed elements, and when you want to clear the file, you instead change the element key to something new, as that should cause it to create a new DOM element and dispose of the old one, leaving the value unset again.

3 Likes