Saltar al contenido
dom-crear-elementos.js · devschool

Modificar el DOM con JavaScript

Lección 27 de 38 · 4 min de lectura · Actualizado el

En esta lección
  1. Los tres pasos
  2. Dónde colocarlo
  3. Reemplazar y borrar
  4. Crear elementos con atributos
  5. Construir contenido a partir de datos
  6. Una tabla fila a fila
  7. innerHTML con plantillas: cómodo pero con cuidado
  8. <template>: moldes en el HTML
  9. Generar contenido al cargar la página

En la lección anterior cambiabas elementos que ya estaban en el HTML. Pero muchas veces el contenido depende de datos: una lista de productos que llega de un servidor, las tareas que añade el usuario, los resultados de una búsqueda. En esos casos hay que crear los elementos con JavaScript.

Los tres pasos

// 1. Crear el elemento
const parrafo = document.createElement("p");

// 2. Rellenarlo: texto, clases, atributos
parrafo.textContent = "Soy un párrafo nuevo";
parrafo.classList.add("aviso");

// 3. Colocarlo en la página
document.querySelector("#contenedor").append(parrafo);

createElement recibe el nombre de cualquier etiqueta ("li", "img", "button", "tr"…). Hasta que no lo colocas con append o similar, el elemento existe en memoria pero no se ve.

Dónde colocarlo

Dado un elemento de referencia, hay cuatro posiciones posibles:

referencia.before(nuevo);    // justo ANTES, fuera de la referencia
referencia.prepend(nuevo);   // DENTRO, al principio
referencia.append(nuevo);    // DENTRO, al final
referencia.after(nuevo);     // justo DESPUÉS, fuera de la referencia
[before]
<ul id="referencia">
   [prepend]
   <li>...</li>
   [append]
</ul>
[after]

Los cuatro aceptan varios elementos a la vez y también texto: lista.append(li1, li2, "texto suelto").

(En código antiguo verás appendChild e insertBefore. Hacen lo mismo con una sintaxis más incómoda.)

append frente a textContent

  • textContent = ... sustituye todo lo que había dentro del elemento, y solo sirve para texto.
  • append(...) añade al final, sin borrar lo que había, y sirve para elementos y texto.

Para vaciar un elemento antes de volver a rellenarlo: lista.replaceChildren() (sin argumentos) o lista.textContent = "".

Reemplazar y borrar

viejo.replaceWith(nuevo);   // pone "nuevo" en el sitio de "viejo"
elemento.remove();          // lo quita de la página

Para borrar varios, selecciónalos por una clase y recórrelos:

for (const tarea of document.querySelectorAll(".completada")) {
  tarea.remove();
}

Por eso es buena idea añadir una clase a los elementos que creas: luego es fácil encontrarlos todos.

Crear elementos con atributos

Cada atributo HTML es una propiedad del objeto:

const img = document.createElement("img");
img.src = "img/gato.jpg";
img.alt = "Gato atigrado durmiendo en una caja";
img.width = 300;

const enlace = document.createElement("a");
enlace.href = "https://developer.mozilla.org/es/";
enlace.textContent = "MDN";
enlace.target = "_blank";
enlace.rel = "noopener";

Construir contenido a partir de datos

El caso más habitual: tienes un array de objetos y quieres mostrarlos. Crea una función que reciba un dato y devuelva un elemento:

function crearTarjeta(producto) {
  const tarjeta = document.createElement("article");
  tarjeta.classList.add("tarjeta");

  const titulo = document.createElement("h3");
  titulo.textContent = producto.nombre;

  const precio = document.createElement("p");
  precio.textContent = `${producto.precio.toFixed(2)} €`;

  tarjeta.append(titulo, precio);
  return tarjeta;
}

const productos = [
  { nombre: "Taza", precio: 8 },
  { nombre: "Camiseta", precio: 19.5 },
];

const galeria = document.querySelector("#galeria");
galeria.replaceChildren(...productos.map(crearTarjeta));

Con map conviertes cada producto en una tarjeta, y con replaceChildren(...) las colocas todas de una vez, sustituyendo lo que hubiera.

Una tabla fila a fila

Las tablas se construyen igual: crear la fila, crear cada celda, meter las celdas en la fila y la fila en la tabla.

function agregarFila(tabla, valores) {
  const tr = document.createElement("tr");
  for (const valor of valores) {
    const td = document.createElement("td");
    td.textContent = valor;
    tr.append(td);
  }
  tabla.append(tr);
}

agregarFila(document.querySelector("#registro"), [1, new Date().toLocaleTimeString("es-ES")]);

innerHTML con plantillas: cómodo pero con cuidado

Construir mucho HTML elemento a elemento es largo. Con innerHTML y una plantilla de texto es más corto:

galeria.innerHTML = productos
  .map((p) => `<article class="tarjeta"><h3>${p.nombre}</h3><p>${p.precio} €</p></article>`)
  .join("");

Es aceptable solo si los datos son tuyos. Si alguno viene de un usuario (un comentario, un nombre), podría contener etiquetas <script> o atributos maliciosos que se ejecutarían en tu página (ataque XSS). Con textContent, en cambio, cualquier texto se muestra tal cual, sin interpretarse. Ante la duda, usa createElement y textContent.

<template>: moldes en el HTML

Si la estructura es grande, puedes escribirla en el HTML dentro de un <template>, que el navegador no muestra, y clonarla desde JavaScript:

<template id="molde-tarea">
  <li class="tarea">
    <input type="checkbox">
    <span class="texto"></span>
    <button class="borrar" aria-label="Borrar tarea">✕</button>
  </li>
</template>
const molde = document.querySelector("#molde-tarea");

function crearTarea(texto) {
  const copia = molde.content.cloneNode(true);
  copia.querySelector(".texto").textContent = texto;
  return copia;
}

document.querySelector("#tareas").append(crearTarea("Estudiar el DOM"));

Así el HTML queda en el HTML y el JavaScript solo rellena los huecos.

Generar contenido al cargar la página

No todo tiene que ocurrir al pulsar un botón. Si llamas a tus funciones directamente en el script, se ejecutan al cargar la página:

function pintarProductos() { /* ... */ }
pintarProductos();   // se ejecuta al cargar

Un detalle importante: si una imagen o un elemento va a rellenarse con JavaScript, rellénalo al cargar con un valor inicial. Una página que al abrirse muestra huecos vacíos o imágenes rotas parece estropeada.

Pruébalo tú

Cambia el código y pulsa Ejecutar (o Ctrl + Enter).

dom-crear-elementos.html
Resultado

Pon a prueba lo que has aprendido

[JavaScript] Después de const p = document.createElement("p"), ¿se ve el párrafo en la página?

[JavaScript] ¿Dónde coloca el nuevo elemento lista.prepend(nuevo)?

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.