W3docs

JavaScript FormData

Aprende la API FormData de JavaScript: crea objetos FormData, lee y modifica campos con get, append, set y delete, envía datos y archivos con fetch, y cómo se compara con URLSearchParams.

Manejar datos de formularios de forma eficiente es esencial para crear páginas web dinámicas e interactivas. JavaScript proporciona la API FormData precisamente para esto: permite recopilar los campos de un formulario, construir conjuntos de pares clave/valor de forma programática y enviarlos a un servidor — incluyendo archivos. Esta guía cubre qué es FormData, cómo crearlo y leerlo, todos los métodos que expone, cómo enviarlo con fetch y los errores más comunes.

Entendiendo FormData

FormData es un objeto JavaScript incorporado que representa un conjunto de pares clave/valor, modelado según la forma en que un navegador envía un formulario HTML. Simplifica la recopilación de información de formularios HTML y su envío a un servidor de forma asíncrona con la API Fetch.

¿Por qué usarlo en lugar de construir un object simple?

  • Lee los campos de un formulario existente automáticamente — sin extracción manual del value por cada campo.
  • Admite archivos y Blobs, que los objetos simples y JSON no pueden transportar.
  • Cuando se pasa a fetch, el navegador establece el Content-Type correcto (multipart/form-data) con el límite adecuado por ti.

Creando objetos FormData

Crea un objeto FormData con el constructor FormData(). Si pasas un elemento <form>, todos los campos con nombre y habilitados de ese formulario se capturan de inmediato. Puedes inspeccionar el contenido iterando su método entries(), que devuelve un iterador de pares [key, value]:

<script>
  function onSubmit(event) {
    event.preventDefault();
    const form = document.getElementById('myForm');
    const formData = new FormData(form);
    let results = '';
    for (const [key, value] of formData.entries()) {
      results += `${key}: ${value}\n`;
    }
    alert(results)
  }
</script>
<form id="myForm" onsubmit="onSubmit(event)">
  <input type="text" name="username" value="John Doe" />
  <input type="email" name="email" value="[email protected]" />
  <input type="submit" />
</form>

Accediendo a los datos del formulario

Lee un campo individual con get(), o itera por todos los campos con entries() como se mostró arriba. get() devuelve el primer valor de una clave (o null si no existe):

<form id="myForm" onsubmit="onSubmit(event)">
  <input type="text" name="username" value="John Doe" />
  <input type="email" name="email" value="[email protected]" />
  <input type="submit" />
</form>
<script>
  function onSubmit(event) {
    const form = document.getElementById('myForm');
    const formData = new FormData(form);
    const username = formData.get('username');
    const email = formData.get('email');
    alert(`username: ${username}; email: ${email}`);
  }
</script>

Métodos de FormData

Además de leer un formulario existente, FormData permite construir y modificar el conjunto de datos manualmente. Los siguientes métodos están disponibles en cada instancia:

MétodoQué hace
append(name, value)Agrega un nuevo valor. Si la clave ya existe, conserva el valor anterior y añade otro, por lo que una clave puede tener múltiples valores.
set(name, value)Establece el valor para una clave, reemplazando cualquier valor existente para esa clave.
get(name)Devuelve el primer valor para la clave, o null.
getAll(name)Devuelve un array con todos los valores para la clave.
has(name)Devuelve true si la clave existe.
delete(name)Elimina todos los valores para la clave.
entries() / keys() / values()Iteradores sobre los pares, claves o valores.

La diferencia entre append y set es la fuente de errores más común:

const fd = new FormData();
fd.append('tag', 'js');
fd.append('tag', 'web');   // append keeps both
console.log(fd.getAll('tag'));   // [ 'js', 'web' ]

fd.set('tag', 'html');     // set replaces all
console.log(fd.getAll('tag'));   // [ 'html' ]

console.log(fd.has('tag'));      // true
fd.delete('tag');
console.log(fd.has('tag'));      // false

También puedes construir un FormData completamente en código — sin ningún formulario — añadiendo campos directamente. Un tercer argumento en append/set establece el nombre de archivo cuando el valor es un Blob o File.

Enviando FormData con la API Fetch

Un caso de uso habitual de FormData es enviar datos de formularios al servidor de forma asíncrona. Pasa la instancia de FormData como el body de una solicitud fetch — el navegador establece automáticamente el Content-Type a multipart/form-data con el límite correcto, por lo que no debes establecer ese encabezado tú mismo:

<form id="myForm" onsubmit="onSubmit(event)">
  <input type="text" name="title" value="A title" />
  <input type="text" name="body" value="A body" />
  <input type="submit" value="Submit Post" />
</form>
<div>post id: <span id="response"></span></div>
<script>
  function onSubmit(event) {
    event.preventDefault();
    const form = document.getElementById('myForm');
    const formData = new FormData(form);
    const responseSpan = document.getElementById('response');
    fetch('https://jsonplaceholder.typicode.com/posts', {
        method: 'POST',
        body: formData
    })
      .then(response => response.json())
      .then(data => { responseSpan.innerHTML = data.id; })
      .catch(error => console.error('Error:', error));
  }
</script>
Advertencia

Cuando pasas tu formulario al constructor FormData, este incluye automáticamente todos los campos del formulario HTML, incluyendo los campos ocultos. Esto puede provocar comportamientos inesperados si no tienes cuidado, especialmente si hay campos sensibles o innecesarios en el formulario.

Manejo de subida de archivos

FormData es la forma estándar de subir archivos, ya que produce una solicitud multipart/form-data que puede transportar contenido binario junto con campos de texto. Cuando construyes el FormData a partir de un formulario que contiene un campo <input type="file">, el archivo seleccionado ya está incluido — no es necesario leer input.files y añadirlo de nuevo:

<form id="fileUploadForm">
    <input type="file" name="file" />
    <input type="submit" value="Upload" />
</form>
<script>
    const form = document.getElementById('fileUploadForm');
    form.addEventListener('submit', (event) => {
        event.preventDefault();
        // The file input is captured automatically from the form.
        const formData = new FormData(form);
        fetch('https://httpbin.org/post', {
            method: 'POST',
            body: formData
        })
        .then(response => response.json())
        .then(data => console.log('Upload successful:', data))
        .catch(error => console.error('Error:', error));
    });
</script>

Para adjuntar un archivo que no forma parte de un formulario — por ejemplo, uno seleccionado de forma programática — añádelo explícitamente, opcionalmente dándole un nombre de archivo:

const formData = new FormData();
formData.append('avatar', fileObject, 'profile.png');

FormData vs. URLSearchParams

Ambos envuelven pares clave/valor, pero se serializan de forma diferente. Usa FormData cuando necesites enviar archivos o multipart/form-data. Usa URLSearchParams cuando solo tengas texto y quieras un body compacto application/x-www-form-urlencoded (o una cadena de consulta). Incluso puedes construir uno a partir del otro cuando todos los valores son string:

const fd = new FormData();
fd.append('q', 'cats');
fd.append('page', '2');

const params = new URLSearchParams(fd);
console.log(params.toString());   // q=cats&page=2

Conclusión

FormData es una herramienta versátil y potente para gestionar datos de formularios en aplicaciones JavaScript. Ya sea que estés manejando entradas de texto simples o subidas de archivos complejas, FormData simplifica el proceso y proporciona una interfaz conveniente para interactuar con los datos del formulario. Al dominar FormData, puedes mejorar la interactividad y la capacidad de respuesta de tus aplicaciones web, brindando una experiencia de usuario fluida.

Práctica

Práctica
¿Cuál es un beneficio de usar el objeto FormData en JavaScript?
¿Cuál es un beneficio de usar el objeto FormData en JavaScript?
Was this page helpful?