Desde hace algún tiempo que vengo trabajando con Angular, recientemente en un freelo me vi en la necesidad de hacer la carga de un archivo a un controllador en net core. Actualmente en este proyecto se esta usando Angular Material y me di con la sorpresa que en esta librería no se tienen ninguna alternativa a un input type file.
Luego de buscar un poco y no encontrar una alternativa que me llamara la atención, decidí ver la forma de crear una. Les comparto esta demo por si a alguien le puede resultar útil.
Primero, necesitamos crear nuestro nuevo proyecto en angular, instalar la librería de angular material, crear el componente para cargar el archivo y finalmente, crear un modulo adicional para que concentre todos los módulos correspondientes de angular material, para esto ejecutamos en la consola del vscode los típicos comandos:
ng new UploadFileAngularMaterial
cd UploadFileAngularMaterial
npm install --save @angular/material @angular/cdk @angular/animations
ng g m /modules/material
ng g c file-upload
Del lado de la configuración del angular material, no me explayaré mucho dado que hay muchos tutoriales en la red que pueden dar más ejemplo y también puede verlo en el repositorio al final del post.
Para usar los material icons, estoy en el index de la aplicación poniendo el link a la url:
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
Veamos ahora si lo importante de esta demo:
File-Upload
El html del componente tendrá la siguiente estructura:
Como se puede observar, tenemos un botón para hacerla carga (una imagen), y debajo de este una lista de los archivos que queramos cargar, en la cual se muestra el nombre del archivo, una barra de progreso, y dos iconos que actúan a modo de botones para reintentar en caso la carga no se haya podido efectuar y para cancelar la carga. Finalmente, nuestro input type file.
Sólo explicaré los métodos más importantes del componente dado que se tienen creado varios:
Para nuestro componente, tenemos algunas variables que pueden ser input del componente, y un output del tipo string. Además, la información que se selecciones los ‘files’ so del tipo ‘FileUploadModel’, paso a detallar lo que contiene este model.
Este modelo posee cierta información que usaremos para manejar la carga del archivo, los estamos que tiene, si se puede re-intentar o cancelar así como las subscripciones que se realizan cuando se hacen las peticiones http.
Cada ves que se realice un click al botón, se está obteniendo el input type file y se busca el evento ‘onchange’, mediante el cual se obtiene los items seleccionados (archivos de texto para el demo). Dado que el evento ‘onchange’, se va activar cuando este cambie, se llama al evento ‘click’ para que abra el buscar de archivos desde el navegador, de manera que cuando estos sean seleccionados se carguen los archivos, y recién se llama al método ‘uploadFiles’.
Se empieza a iterar sobre los archivos seleccionados que se llenaron en el evento ‘onchange’ y cada uno de estos estos serán enviados al método ‘uploadFile’.
Este es el método que se encarga de hacer la carga del archivo, para la demo estoy usando un api pública «http://file.io» que te permite realizar la carga de archivos. También se podría llamar a algún service de ser necesario o el modo en le cual deseen consumir servicios desde su aplicativo. Acá, estamos inicializando un HttpRequest del tipo post, y asignado el request a nuestro ‘sub’ que es parte de nuestra entidad. Adicionalmente, vamos a mapear un evento para poder determinar el avance del progress conforme se va cargando el archivo, tenemos una suscripción para manejar lo que nos retorne la suscripción en caso de que la respuesta HTPP sea del tipo 200, si fuera alguna respuesta HTTP de error, entrará a nuestro ‘catchError’. De ser correcto, limpiamos el archivo y le enviamos la respuesta al output del tipo eventEmitter, al componente que este llamandonos. Veamos una demo de como se está dando todo este proceso:
Si quisieramos revisar si la carga fue correcta, podemos abrir el link que se adjunta en el response, teniendo el siguiente resultado.
Aún cuando el dedsarrollo del componente me tomo mas tiempo del que hubiera deseado, es una buena idea tenerlo como una herramienta más en el repertorio. Dejo un video de la creación del proyecto y las pruebas que se han realizado, además del link al repositorio.
13 comentarios