Agregando más campos al formulario

En este artículo vamos a ampliar / modificar lo que hemos hecho anteriormente. Vamos a agregar más campos a nuestro formulario. Dicho así puede parecer algo banal. Más campos, una estructura de la clase Member más compleja, un poco más de procesamiento… más de lo mismo. Pues no. En este artículo vamos a incluir un campo de fecha (eso sí podría ser más de lo mismo), y también un campo de tipo file. Envir estos tipos de campos puede parecer muy simple con un formulario tradicional, pero no es lo mismo cuando queremos hacerlo desde JavaScript y, menos aún, cuando queremos integrar esa funcionalidad en Angular.

Aquí ya debemos recurrir al uso de un objeto de tipo FormData() y a otras cosas complementarias, y la cosa se complica un poco… pero sólo un poco.

Vamos a centrarnos en esto durante este artículo para que, cuando tengamos esa necesidad, sepamos como hacer las cosas.

LO QUE QUEREMOS HACER

En este artículo vamos a ver como podemos hacer el formulario un poco más complejo. Como hemos dicho, vamos a añadir un campo de fecha, para anotar la fecha en que se da de alta a un nuevo socio, y un campo de fichero, para almacenar un avatar o fotografía del nuevo socio. Además, en la edición, veremos el avatar del socio, y tendremos opción a modificarlo o dejarlo como está.

La verdad es que estas funcionalidades modifican un poco las API’s en PHP (lo que no es relevante, desde el punto de vista del código Angular), y también nos modifica bastante el servicio que se ocupa de todo (members.service.ts).

Sin embargo, vamos a ver que casi todas las modificaciones que hacemos en el servicio son cosa de JavaScript, no de Angular. El código Angular opera igual que en el ejemplo anterior. Si conoces JavaScript (y si estás siguiendo este curso entiendo que es así) verás que la gran mayoría de los cambios y ampliaciones son eso: JavaScript. Las tendríamos que hacer igual aunque nuestro CRUD no fuera una aplicación Angular.

COMO HACERLO

Lo primero que vemos es que tenemos una nueva variable (bueno, algunas más, pero vamos por partes) que define un objeto FormData:

private dataPack = new FormData();

Cuando vamos a grabar un usuario, tanto si es un usuario nuevo como una edición de un usuario existente, ya no podemos pasarle al método que comunica con la API el objeto de la clase Member. Debido a que este sólo es una matriz de literales, de alguna forma tenemos que añadir la imagen, si la hay. La solución pasa por empaquetar todo, objeto de clase Member y fichero de la imagen. Ambos datos los empaquetamos en el objeto FormData y es este el que le pasamos al método que comunica con la API. Sin embargo, esto nos plantea otro problema. A un objeto FormData, como sabes, no se le puede añadir directamente una matriz con el método append(). No nos queda más remedio que serializar la matriz en JSON antes de empaquetarla. Esto nos obliga a crear un método adicional, como vemos a continuación:

Además, observa que, cuando llegamos a este método, ya tenemos el archivo de imagen, si se ha seleccionado alguno, en la propiedad avatarFile de la clase del servicio. Pero para obtener esto, hemos tenido que dar dos pasos previos. El primero, evidentemente, asegurarnos de que el fichero sea una imagen en formato .jpg. Lo hemos limitado a este formato por simplificar. Podríamos haber admitido otros formatos de imagen, pero no he querido perderme en más florituras de JS (bastantes va a tener ya el código). Además, nos aseguraremos de que la imagen tenga un peso máximo que, en este caso, hemos establecido en 40 Kb. El otro paso es leer el fichero para convertirlo en un objeto blob que podamos empaquetar en el objeto FormData. Estos dos pasos los hemos dado añadiendo un código adicional al método checkRecord() que ya teníamos de antes:

Por lo demás, una vez empaquetado el objeto FormData, lo enviamos al método que, a su vez, llama a la API:

Como ves, aquí las diferencias son mínimas. La única cuestión es que estos métodos, en lugar de trabajar con un objeto de la clase Member, reciben y envían un objeto de la clase FormData. Si quieres saber más sobre objetos FormData, y la forma de empaquetar datos, te recomiendo que leas este artículo. Está orientado a trabajar con jQuery, no con Angular, pero ilustra perfectamente la operativa de estos objetos.

EN LA API

Esta forma de trabajar plantea una diferencia sustancial en lo que a la API en PHP respecta. Nos salimos un poco del tema, pero quiero comentártelo, porque lo considero importante para tener en cuenta. Los datos ya no son recibidos por PHP a través de la envolvente php://input, como en el caso anterior. Cuando Angular envía un objeto de la clase FormData, en PHP se reciben los datos en las matrices globales convencionales ($_POST y $_FILES).

EL AVATAR

Puestos a refinar nuestro CRUD, me propuse que cuando el usuario seleccione una imagen como avatar (si es conforme a los criterios que hemos establecido), se muestre dicha imagen en la página antes de subirla al servidor. De este modo, el usuario tiene una previsualización, para determinar si ha elegido la imagen correcta. La única forma de hacer esto en mediante la clase FileReader (una vez más, JavaScript, no Angular). Lo ves en uno de los métodos nuevos que hemos añadido en esta versión del CRUD:

Además, cuando seleccionamos un socio para editar, podemos visualizar su avatar actual.

Como ves, se han añadido otras variables, para mostrar mensajes de aviso adicionales, y complementar las funcionalidades de los métodos empleados. Sin embargo, la cuestión realmente importante es que todo lo que hemos añadido es JavaScript. En el código Angular, como ves, los cambios son mínimos.

CONCLUYENDO

Como ya es habitual, te he dejado el código para descargar en este enlace. En el archivo ang-http.zip tienes la aplicación completa, para seguir el código. Verás que, si bien al principio puede abrumarte un poco, no hay nada que no conozcas ya. En el archivo apis_extended_php.zip tienes las API’s de PHP, y la estructura de la base de datos. Además, hay un directorio llamado avatares, donde se almacenarán los avatares de los usuarios que crees. Ten en cuenta, si trabajas con Mac o Linux, que debes darle a este directorio permios de escritura (0777 o, al menos, 0755). Por último, en el archivo ang_iconos_pruebas.zip tienes unos avatares de ejemplo para hacer tus pruebas con el CRUD.

   

Deja un comentario