Saltar al contenido

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript... y lo que venga ;)

17 años online

el blog de José M. Aguilar

Inicio El autor Contactar

Artículos, tutoriales, trucos, curiosidades, reflexiones y links sobre programación web
ASP.NET Core, MVC, Blazor, SignalR, Entity Framework, C#, Azure, Javascript...

¡Microsoft MVP!
martes, 15 de noviembre de 2011
No es algo excesivamente frecuente, pero en ocasiones podemos necesitar limpiar el valor de un campo de tipo file (el que usamos para hacer los uploads) de un formulario, por ejemplo, para evitar que el usuario envíe un archivo que por cualquier motivo no deba ser subido al servidor.

O dicho de otra forma, imaginemos la siguiente porción de un formulario en pantalla, que podría ser generada con el código que podéis ver justo a continuación:
Campo de envío de archivos
<label for="archivo">Archivo a enviar:</label>
<input type="file" id="archivo" name="archivo" />
<input type="button" onclick="limpiarInputFile('archivo');" value="Limpiar" />

Y la pregunta en este momento sería, ¿qué código deberíamos implementar en la función limpiarInputFile() que estamos utilizando en el evento onclick si quisiéramos limpiar o inicializar el contenido del campo archivo?

Aunque de forma intuitiva podría parecer que basta con establecer el valor del campo a una cadena vacía, una prueba rápida nos demostrará que esto no es posible. Desde hace ya tiempo, por motivos de seguridad, los navegadores no permiten el acceso de escritura a la propiedad value en los campos de envío de archivos, por lo que nos encontramos una vía sin salida. Esto lo vemos con el siguiente código, utilizando jQuery:

    function limpiarInputfile(id) {
        var input = $('#' + id);
        var nuevoValor = "c:\\windows\\system32\\mspaint.exe";
        
        alert(input.val());       // Muestra "C:\Datos.dat"
        input.val(nuevoValor);    // Establecemos un nuevo valor
        alert(input.val());       // ¡¡Muestra "C:\Datos.dat"!!
    }

Como vemos, somos vilmente ignorados cuando intentamos establecerle un valor.

Pues bien, una posible solución consiste en eliminar del DOM el elemento <input type="file"> y volver a crearlo justo después en el mismo lugar. He visto por ahí varias implementaciones que obligaban a introducir este elemento dentro de un contenedor, pero he creado otra que creo que es más sencilla e igual de efectiva:

    function limpiarInputfile(id) {
        var input = $('#' + id);
        var clon = input.clone();  // Creamos un clon del elemento original
        input.replaceWith(clon);   // Y sustituimos el original por el clon
    }

Y eso es todo :-). Observad que lo único que hacemos es crean un clon del elemento original cuyo value por supuesto estará en blanco (recordad que esta propiedad no se puede establecer), y justo a continuación eliminamos el elemento original sustituyéndolo por este clon.

Si queremos generalizar este código e implementar esta funcionalidad de forma no intrusiva podríamos hacer lo siguiente:

    $(function () {
        $("input[type=file]").after(
            "<input type='button' class='limpiar-inputfile' value='Limpiar'>"
        );
        $(".limpiar-inputfile").click(function () {
            var input = $(this).prev("input[type=file]");
            var clon = input.clone();
            input.replaceWith(clon);
            return false;
        });
    });

Este código añade automáticamente un botón “Limpiar” a continuación de todos los <input type=file> de la página, implementando en el manejador del evento click la lógica de inicialización del componente que hemos visto antes. De esta forma, sólo se introducirá en la página el botón de limpiado cuando estén activados los scripts, que es en el único momento en que su ejecución tendrá sentido con la solución propuesta.

Espero que os sea de utilidad.

Publicado en: Variable not found.

10 Comentarios:

Anónimo dijo...

<button type="reset" >Reiniciar formulario</button>
<input type="reset" value="Reiniciar formulario"/>

http://www.w3.org/TR/1999/REC-html401-19991224/interact/forms.html#reset-button

josé M. Aguilar dijo...

Hola!


Ya, el problema que tiene el reset es que inicializa el contenido de todos los campos del formulario, y eso no es conveniente en algunos escenarios.

Esta técnica muestra cómo limpiar exclusivamente los campos type=file.

Saludos & gracias por comentar.

Anónimo dijo...

Hola! a mi la verdad no me funcionó =( no sé si es porque estoy usando JQuery 1.9. En el navegador me sale este error: Uncaught TypeError: Object # has no method 'map'
Justo antes de esta linea: input.replaceWith(clon);
Te agradezco tu ayuda

josé M. Aguilar dijo...

Hola!

Vaya, pues acabo de probar con jQuery 1.9 y sí que me funciona... mira a ver si tienes otro código que pueda estar interfiriendo, por ejemplo, créate una página sólo con el input file, jquery, y este script, y debe funcionar.

Saludos.




Anónimo dijo...

A mi me sirvio...gracias

desde peru Alberto cabrera

Anónimo dijo...

Hola, a mi si me funcionó. Lo inconveniente es que como es nuevo pues el DOM ya no me reconce los eventos.
Sin embargo ya hay una nueva forma de hacerlo; desconozco si antes al publicar este articulo existia.

La solución mas obtima y rapida es.
$('#id').val(null);

Con el null borra el contenido.
Saludos.

Anónimo dijo...

Phillips7...
que versión de jquery usas porque lo que señalas como solución no funciona

La solución mas obtima y rapida es.
$('#id').val(null);

HectorOcampo.co dijo...

Hola, a mí tampoco me funcionó el script porque al clonarlo me clona el input con todo y nombre del archivo seleccionado. No sé si entonces hay que clonarlo cuando está vacío. El problema es que en mi caso son input files que se crean dinamicamente.

SOFTMURILLO dijo...

Muy bien amigo gracias

drf dijo...

A quienes no les funciona el clonado, se debe a que luego de crear el clon del Nodo deben resetear su valor estableciéndolo a vacío o nulo. Luego sí procedemos al reemplazo.