formdata

js/globals/formdata.ts

FormData global (WHATWG XHR / Fetch spec).

Learn more:

FormData is the standard representation of an HTML form submission. It holds an ordered list of name/value entries where values are either strings or File objects (Blobs with a filename). It is used as a request body in the Fetch API and as the basis for multipart/form-data serialization. This release supports outgoing multipart/form-data serialization only; parsing incoming multipart request bodies into FormData is intentionally outside the release scope.

Fino also supports new FormData(existingFormData) as a nonstandard convenience extension for shallow-copying entries. Browser constructors accept an HTML form element instead.

Entry normalization (_normalizeEntry)

The WHATWG spec requires that values be normalized on insertion:

The wrapping-in-File step is non-obvious: even if the value is already a File, it gets re-wrapped into a new File if a filename argument is explicitly provided. This matches the spec and allows callers to override the filename at append time.

Entry ordering and duplicates

FormData is an ordered list, not a map. Multiple entries can share the same name. get() returns only the first match; getAll() returns all matches. set() replaces the first match and removes all subsequent ones, preserving the position of the first occurrence. delete() removes all entries with the given name.

Iteration

The [Symbol.iterator]() method delegates to entries(), so FormData instances can be iterated with for...of to get [key, value] pairs, matching the browser API. Iterators are live and read from the current entry list as they advance, so entries appended before completion can be observed and entries deleted before their turn are skipped.

// FormData is available via globalThis

const fd = new FormData();
fd.append('name', 'Alice');
fd.append('avatar', blob, 'avatar.png');

fd.get('name');     // 'Alice'
fd.getAll('name');  // ['Alice']
fd.has('name');     // true
fd.set('name', 'Bob');
fd.delete('name');

for (const [key, value] of fd) { ... }
fd.forEach((value, key, fd) => { ... });

Types

type FormDataEntryValue = string | File

Value stored in a FormData entry.

String entries represent regular form fields. File entries represent Blob values after FormData normalizes them with a filename for multipart/form-data serialization.

Classes

class FormData {

Ordered collection of string and File form entries.

Duplicate names are allowed and insertion order is preserved. Blob values are normalized into File entries so multipart serialization always has a filename.

const form = new FormData();
form.append('name', 'Alice');
form.get('name'); // "Alice"

Constructors

constructor(init?: FormData)

Create an empty FormData or shallow-copy an existing FormData.

The copy-constructor form is a nonstandard Fino extension. It preserves entry order and does not deep-clone File objects.

const source = new FormData();
source.append('x', '1');
const copy = new FormData(source);

Methods

append(name: string, value: string | Blob, filename?: string): void

Append a new entry without removing existing entries with the same name.

Names and string values are string-coerced and line endings are normalized to CRLF. Blob values become File values: the filename argument sets the name, otherwise a plain Blob defaults to "blob" and an existing File keeps its own name.

const form = new FormData();
form.append('tag', 'a');
form.append('tag', 'b');
form.getAll('tag'); // ["a", "b"]
delete(name: string): void

Remove every entry with the given name.

Unknown names are ignored. The name is string-coerced before matching.

const form = new FormData();
form.append('x', '1');
form.delete('x');
form.has('x'); // false
get(name: string): FormDataEntryValue | null

Return the first value for a name, or null when absent.

File entries are returned as File instances. Duplicate entries after the first are ignored by this method.

const form = new FormData();
form.append('x', '1');
form.get('x'); // "1"
getAll(name: string): FormDataEntryValue[]

Return all values for a name in insertion order.

The returned array is new, so mutating it does not affect the FormData.

const form = new FormData();
form.append('x', '1');
form.append('x', '2');
form.getAll('x'); // ["1", "2"]
has(name: string): boolean

Return true when at least one entry exists for name.

const form = new FormData();
form.append('x', '1');
form.has('x'); // true
set(name: string, value: string | Blob, filename?: string): void

Replace entries for a name with a single normalized entry.

The first matching position is preserved and later duplicates are removed. If the name did not exist, the new entry is appended.

const form = new FormData();
form.append('x', '1');
form.set('x', '2');
form.getAll('x'); // ["2"]
*entries(): IterableIterator<[string, FormDataEntryValue]>

Iterate over [name, value pairs in insertion order.

The iterator is live and reads the current entry list as it advances.

const form = new FormData();
form.append('x', '1');
[...form.entries()]; // [["x", "1"]]
*keys(): IterableIterator<string>

Iterate over entry names in insertion order.

Duplicate names appear once for each entry.

const form = new FormData();
form.append('x', '1');
[...form.keys()]; // ["x"]
*values(): IterableIterator<FormDataEntryValue>

Iterate over values in insertion order.

Values are strings or File objects.

const form = new FormData();
form.append('x', '1');
[...form.values()]; // ["1"]
forEach( callback: ( value: FormDataEntryValue, name: string, parent: FormData ) => void, thisArg?: unknown ): void

Call a callback for each entry in insertion order.

The callback receives value, name, and the FormData object. thisArg is used as the callback receiver when provided.

const form = new FormData();
form.append('x', '1');
form.forEach((value, name) => console.log(name, value));