Como vimos en capítulos anteriores, en Ajax hay varios pasos que seguir:
- Crear la instancia del objeto.
- El listener.
- Abrir la petición.
- Enviar la petición.
Para cada una de las 4 operaciones del CRUD tendríamos que hacer lo mismo en Ajax, entonces lo que conviene es justamente lo que hacen librerías como Axios, crear una función que encapsule todo y pida los elementos necesarios.
Es importante levantar el servidor, al estar utilizando la API falsa de JSON Placeholder, para ello utilizamos la siguiente sintaxis.
json-server -w -p 5555 assets/db.json
De esta manera levantamos el archivo db.json que se encuentra en la carpeta assets de nuestro servidor.
Vamos a crear una función ajax() a la que le vamos a pasar un objeto, y utilizaremos la destructuración de dicho objeto.
const ajax = (options) => { let(url, method, success, error, data} = options; }
Así como un documento tiene cabecera y cuerpo, las peticiones HTTP tienen también cabecera, en este caso hay que incluir en nuestro script que el tipo de contenido es de tipo application/json, para lo que incluiremos la siguiente sintaxis. Vamos a aprender como agregar cabeceras a las peticiones HTTP. Para ello se utiliza un método denominado setRequestHeader(), de la siguiente forma
xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8");
Si le quitamos esta cabecera, el JSON Server que está esperando no va a funcionar.
Veamos la sintaxis completa del ejm.
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>CRUD API REST Ajax</title> </head> <body> <h1>CRUD API REST Ajax</h1> <section id="crud"> <article> <h2 class="crud-title">Agregar nombre</h2> <form class="crud-form"> <input type="hidden" name="id" /> <input type="text" name="nombre" placeholder="nombre" required /> <br /> <input type="email" name="constelacion" placeholder="constelación" required /> <br /> <input type="submit" value="Enviar" /> </form> </article> <article> <h2>Ver nombres</h2> <table class="crud-table"> <thead> <tr> <th>Nombre</th> <th>Constelación</th> <th>Acciones</th> </tr> </thead> <tbody></tbody> </table> </article> </section> <template id="crud-template"> <tr> <td class="name"></td> <td class="constellation"></td> <td> <button class="edit">Editar</button> <button class="delete">Eliminar</button> </td> </tr> </template> <script> const d = document, $table = d.querySelector(".crud-table"), $form = d.querySelector(".crud-form"), $title = d.querySelector(".crud-title"), $template = d.getElementById("crud-template").content, $fragment = d.createDocumentFragment(); const ajax = (options) => { // Usamos destructuración let { url, method, success, error, data } = options; const xhr = new XMLHttpRequest(); xhr.addEventListener("readystatechange", (e) => { if (xhr.readyState !== 4) return; if (xhr.status >= 200 && xhr.status < 300) { let json = JSON.parse(xhr.responseText); success(json); } else { let message = xhr.statusText || "Ocurrió un error"; error(`Error ${xhr.status}: ${message}`); } }); xhr.open(method || "GET", url); xhr.setRequestHeader("Content-Type", "application/json; charset=utf-8"); xhr.send(JSON.stringify(data)); }; const getAll = () => { ajax({ url: "http://localhost:5555/santos", success: (res) => { console.log(res); res.forEach((el) => { $template.querySelector(".name").textContent = el.nombre; $template.querySelector(".constellation").textContent = el.constelacion; $template.querySelector(".edit").dataset.id = el.id; $template.querySelector(".edit").dataset.name = el.nombre; $template.querySelector(".edit").dataset.constellation = el.constelacion; $template.querySelector(".delete").dataset.id = el.id; let $clone = d.importNode($template, true); $fragment.appendChild($clone); }); $table.querySelector("tbody").appendChild($fragment); }, error: (err) => { console.log(err); $table.insertAdjacentHTML("afterend", `<p><b>${err}</b></p>`); }, }); }; d.addEventListener("DOMContentLoaded", getAll); </script> </body> </html>
El archivo JSON sobre el que trabaja este script es el siguiente: