Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use fetch in FormData guide #30295

Merged
merged 5 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions files/en-us/web/api/formdataevent/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ browser-compat: api.FormDataEvent

The **`FormDataEvent`** interface represents a [`formdata` event](/en-US/docs/Web/API/HTMLFormElement/formdata_event) — such an event is fired on an {{domxref("HTMLFormElement")}} object after the entry list representing the form's data is constructed. This happens when the form is submitted, but can also be triggered by the invocation of a {{domxref("FormData.FormData", "FormData()")}} constructor.

This allows a {{domxref("FormData")}} object to be quickly obtained in response to a `formdata` event firing, rather than needing to put it together yourself when you wish to submit form data via a method like {{domxref("XMLHttpRequest")}} (see [Using FormData objects](/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects)).
This allows a {{domxref("FormData")}} object to be quickly obtained in response to a `formdata` event firing, rather than needing to put it together yourself when you wish to submit form data via a method like {{domxref("fetch()")}} (see [Using FormData objects](/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects)).

{{InheritanceDiagram}}

Expand Down Expand Up @@ -74,7 +74,7 @@ formElem.addEventListener("formdata", (e) => {

## See also

- {{domxref("XMLHTTPRequest")}}
- {{domxref("fetch()")}}
- {{domxref("FormData")}}
- [Using FormData objects](/en-US/docs/Web/API/XMLHttpRequest_API/Using_FormData_Objects)
- {{HTMLElement("Form")}}
Original file line number Diff line number Diff line change
Expand Up @@ -6,41 +6,46 @@ page-type: guide

{{DefaultAPISidebar("XMLHttpRequest API")}}

The [`FormData`](/en-US/docs/Web/API/FormData) object lets you compile a set of key/value pairs to send using [`XMLHttpRequest`](/en-US/docs/Web/API/XMLHttpRequest). It is primarily intended for use in sending form data, but can be used independently from forms in order to transmit keyed data. The transmitted data is in the same format that the form's {{domxref("HTMLFormElement.submit","submit()")}} method would use to send the data if the form's encoding type were set to `multipart/form-data`.
The [`FormData`](/en-US/docs/Web/API/FormData) object lets you compile a set of key/value pairs to send using the [Fetch](/en-US/docs/Web/API/Fetch_API) or [XMLHttpRequest](/en-US/docs/Web/API/XMLHttpRequest_API) API. It is primarily intended for use in sending form data, but can be used independently from forms in order to transmit keyed data. The transmitted data is in the same format that the form's {{domxref("HTMLFormElement.submit","submit()")}} method would use to send the data if the form's encoding type were set to `multipart/form-data`.

## Creating a `FormData` object from scratch

You can build a `FormData` object yourself, instantiating it then appending fields to it by calling its {{domxref("FormData.append","append()")}} method, like this:

```js
const formData = new FormData();

formData.append("username", "Groucho");
formData.append("accountnum", 123456); // number 123456 is immediately converted to a string "123456"

// HTML file input, chosen by user
formData.append("userfile", fileInputElement.files[0]);

// JavaScript file-like object
const content = '<q id="a"><span id="b">hey!</span></q>'; // the body of the new file…
const blob = new Blob([content], { type: "text/xml" });

formData.append("webmasterfile", blob);

const request = new XMLHttpRequest();
request.open("POST", "https://example.com/submitform.php");
request.send(formData);
const send = document.querySelector("#send");

send.addEventListener("click", async () => {
const formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456);

// A file <input> element
const avatar = document.querySelector("#avatar");
formData.append("avatar", avatar.files[0]);

// JavaScript file-like object
const content = '<q id="a"><span id="b">hey!</span></q>';
const blob = new Blob([content], { type: "text/xml" });
formData.append("webmasterfile", blob);

const response = await fetch("http://example.org/post", {
method: "POST",
body: formData,
});
console.log(await response.json());
});
```

> **Note:** The fields "userfile" and "webmasterfile" both contain a file. The number assigned to the field "accountnum" is immediately converted into a string by the [`FormData.append()`](/en-US/docs/Web/API/FormData/append) method (the field's value can be a {{ domxref("Blob") }}, {{ domxref("File") }}, or a string: **if the value is neither a `Blob` nor a `File`, the value is converted to a string**).
> **Note:** The fields `"avatar"` and `"webmasterfile"? both contain a file. The number assigned to the field `"accountnum"` is immediately converted into a string by the [`FormData.append()`](/en-US/docs/Web/API/FormData/append) method (the field's value can be a {{ domxref("Blob") }}, {{ domxref("File") }}, or a string: _if the value is neither a `Blob` nor a `File`, the value is converted to a string_).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[mdn-linter] reported by reviewdog 🐶

Suggested change
> **Note:** The fields `"avatar"` and `"webmasterfile"? both contain a file. The number assigned to the field `"accountnum"` is immediately converted into a string by the [`FormData.append()`](/en-US/docs/Web/API/FormData/append) method (the field's value can be a {{ domxref("Blob") }}, {{ domxref("File") }}, or a string: _if the value is neither a `Blob` nor a `File`, the value is converted to a string_).
> **Note:** The fields `"avatar"` and `"webmasterfile"? both contain a file. The number assigned to the field`"accountnum"`is immediately converted into a string by the [`FormData.append()`](/en-US/docs/Web/API/FormData/append) method (the field's value can be a {{ domxref("Blob") }}, {{ domxref("File") }}, or a string: _if the value is neither a`Blob`nor a`File`, the value is converted to a string\_).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why it wants to do this.

wbamberg marked this conversation as resolved.
Show resolved Hide resolved

This example builds a `FormData` instance containing values for fields named "username", "accountnum", "userfile" and "webmasterfile", then uses the `XMLHttpRequest` method [`send()`](/en-US/docs/Web/API/XMLHttpRequest/send) to send the form's data. The field "webmasterfile" is a {{domxref("Blob")}}. A `Blob` object represents a file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The {{ domxref("File") }} interface is based on `Blob`, inheriting blob functionality and expanding it to support files on the user's system. In order to build a `Blob` you can invoke [the `Blob()` constructor](/en-US/docs/Web/API/Blob/Blob).
This example builds a `FormData` instance containing values for fields named `"username"`, `"accountnum"`, `"avatar"` and `"webmasterfile"`, then uses {{domxref("fetch()")}} to send the form's data. The field `"webmasterfile"` is a {{domxref("Blob")}}. A `Blob` object represents a file-like object of immutable, raw data. Blobs represent data that isn't necessarily in a JavaScript-native format. The {{ domxref("File") }} interface is based on `Blob`, inheriting blob functionality and expanding it to support files on the user's system. In order to build a `Blob` you can invoke [the `Blob()` constructor](/en-US/docs/Web/API/Blob/Blob).

## Retrieving a `FormData` object from an HTML form

To construct a `FormData` object that contains the data from an existing {{ HTMLElement("form") }}, specify that form element when creating the `FormData` object:

> **Note:** `FormData` will only use input fields that use the name attribute.
> **Note:** `FormData` will only use input fields that use the `name` attribute.

```js
const formData = new FormData(someFormElement);
Expand All @@ -49,21 +54,37 @@ const formData = new FormData(someFormElement);
For example:

```js
const formElement = document.querySelector("form");
const request = new XMLHttpRequest();
request.open("POST", "submitform.php");
request.send(new FormData(formElement));
const send = document.querySelector("#send");

send.addEventListener("click", async () => {
// A <form> element
const userInfo = document.querySelector("#user-info");
const formData = new FormData(userInfo);

const response = await fetch("http://example.org/post", {
method: "POST",
body: formData,
});
console.log(await response.json());
});
```

You can also append additional data to the `FormData` object between retrieving it from a form and sending it, like this:

```js
const formElement = document.querySelector("form");
const formData = new FormData(formElement);
const request = new XMLHttpRequest();
request.open("POST", "submitform.php");
formData.append("serialnumber", serialNumber++);
request.send(formData);
const send = document.querySelector("#send");

send.addEventListener("click", async () => {
const userInfo = document.querySelector("#user-info");
const formData = new FormData(userInfo);
formData.append("serialnumber", 12345);

const response = await fetch("http://example.org/post", {
method: "POST",
body: formData,
});
console.log(await response.json());
});
```

This lets you augment the form's data before sending it along, to include additional information that's not necessarily user-editable.
Expand All @@ -73,7 +94,7 @@ This lets you augment the form's data before sending it along, to include additi
You can also send files using `FormData`. Include an {{ HTMLElement("input") }} element of type `file` in your {{htmlelement("form")}}:

```html
<form enctype="multipart/form-data" method="post" name="fileinfo">
<form enctype="multipart/form-data" method="post" name="fileinfo" id="fileinfo">
<p>
<label
>Your email address:
Expand Down Expand Up @@ -103,35 +124,24 @@ You can also send files using `FormData`. Include an {{ HTMLElement("input") }}
<input type="submit" value="Stash the file!" />
</p>
</form>
<div id="output"></div>
```

Then you can send it using code like the following:

```js
const form = document.forms.namedItem("fileinfo");
form.addEventListener(
"submit",
(event) => {
const output = document.querySelector("#output");
const formData = new FormData(form);

formData.append("CustomField", "This is some extra data");

const request = new XMLHttpRequest();
request.open("POST", "stash.php", true);
request.onload = (progress) => {
output.innerHTML =
request.status === 200
? "Uploaded!"
: `Error ${request.status} occurred when trying to upload your file.<br />`;
};

request.send(formData);
event.preventDefault();
},
false,
);
const form = document.querySelector("#fileinfo");

form.addEventListener("submit", async (event) => {
const formData = new FormData(form);

formData.append("CustomField", "This is some extra data");

const response = await fetch("stash.php", {
method: "POST",
body: formData,
});
event.preventDefault();
});
```

> **Note:** If you pass in a reference to the form, the [request HTTP method](/en-US/docs/Web/HTTP/Methods) specified in the form will be used over the method specified in the `open()` call.
Expand All @@ -152,7 +162,7 @@ The [`formdata` event](/en-US/docs/Web/API/HTMLFormElement/formdata_event), more

This allows a {{domxref("FormData")}} object to be quickly obtained in response to a `formdata` event firing, rather than needing to put it together yourself.

Typically this is used as shown in our [`formdata` event demo](https://long-impatiens.glitch.me/) — in the JavaScript we reference a form:
For example, in the JavaScript we can reference a form:

```js
const formElem = document.querySelector("form");
Expand Down Expand Up @@ -182,10 +192,11 @@ formElem.addEventListener("formdata", (e) => {
console.log(value);
}

// submit the data via XHR
const request = new XMLHttpRequest();
request.open("POST", "/formHandler");
request.send(data);
// Submit the data via fetch()
fetch("/formHandler", {
method: "POST",
body: data,
});
});
```

Expand All @@ -195,7 +206,7 @@ The `FormData` object doesn't include data from the fields that are disabled or

## See also

- [Using XMLHttpRequest](/en-US/docs/Web/API/XMLHttpRequest_API/Using_XMLHttpRequest)
- [Using the Fetch API](/en-US/docs/Web/API/Fetch_API/Using_Fetch)
- {{domxref("HTMLFormElement")}}
- {{domxref("Blob")}}
- [Typed Arrays](/en-US/docs/Web/JavaScript/Guide/Typed_arrays)