Closed faseidl closed 4 years ago
@faseidl It should be pretty much the same way as you handle text input:
module Form = [%form
type input = { files: array(Webapi.File.t) };
...
];
<input
type_="file"
onChange={event =>
form.updateFiles(
(input, files) => { files: files },
event->ReactEvent.Form.target##files->Js.Array.from,
)
}
/>
P.S. I didn't run the example. Let me know if it doesn't work.
Thanks, Alex! That was a big help! I didn't know about the Webapi module and was at a loss for how to declare the input and access the event data.
Now, the question becomes, how does one take the File object and make a POST request that sends it to a server in ReasonML? Googling for an hour only seems to suggest that nobody has quite figured out how to do the appropriate ReasonML bindings for FormData.
Yeah, bs-webapi
is essential for working with the DOM.
Though it doesn't have FormData
bindings yet and I have it implemented internally. This example should give an idea:
module FormData = {
type t = Fetch.formData;
[@bs.new] external make: unit => t = "FormData";
[@bs.send] external append: (t, string, 'a) => unit = "append";
};
let formData = FormData.make();
formData->FormData.append("file", file);
Fetch.fetchWithInit(
url,
Fetch.RequestInit.make(
~method_=Post,
~body=formData->Fetch.BodyInit.makeWithFormData,
(),
),
);
Ah, your approach is tighter than what I came up with:
/**
* Hacked bindings for FormData that provide just enought functionatity to do file uploads
* in ReasonML.
*
* To use, add the following script to your application's index.html file.
*
* <!-- FasHacks -->
<script>
let FasHacks = {
formData: {
create: function() {
return new FormData();
},
append: function (formdata, key, value) {
formdata.append(key, value);
return formdata;
}
}
}
</script>
*/
module FormData = {
[@bs.val] external create: unit => Js.t('a) = "FasHacks.formData.create";
[@bs.val]
external appendString: (Js.t('a), string, string) => Js.t('a) =
"FasHacks.formData.append";
[@bs.val]
external appendInt: (Js.t('a), string, int) => Js.t('a) =
"FasHacks.formData.append";
[@bs.val]
external appendFile: (Js.t('a), string, Webapi.File.t) => Js.t('a) =
"FasHacks.formData.append";
};
Then I was able to use it with Axios:
let createNewAsset = (file: Webapi.File.t, title: string) => {
let formdata =
FasHacks.FormData.(
create()->appendFile("file", file)->appendString("title", title)
);
Js.Promise.(
Axios.postData(apiPath("/media-assets"), formdata)
|> then_(response => resolve(Model.MediaAsset.parse(response##data)))
);
};
I believe it can be closed. Feel free to re-open if you have any other questions.
Can you provide (or point me to) an example of using re-formality to create a file upload form? I've not been able to figure out how to handle <input type="file"> fields.