TdnInputImage
Paquete: @tiendana/ngx-core/forms
Componente de carga de imágenes con previsualización, optimización automática, drag & drop y personalización completa.
Características
✅ Preview en vivo - Muestra la imagen seleccionada antes de subirla
✅ Optimización automática - Comprime y redimensiona imágenes con ImageCompressor
✅ Drag & drop - Arrastra imágenes directamente sobre el componente
✅ Restricción de tipos - Acepta solo formatos de imagen
✅ Imágenes existentes - Muestra imágenes ya guardadas con URLs
✅ Object-fit configurable - Controla cómo se ajusta la imagen (cover/contain)
✅ Eventos detallados - Controla selección, eliminación y procesamiento
✅ Integración total - Compatible con Reactive Forms y validadores
Selector
<tdn-input-image />
API
Inputs
| Propiedad | Tipo | Descripción | Por Defecto |
|---|---|---|---|
settings | TdnInputImageSettings | Configuración del componente (optimización, textos, iconos, object-fit) | Configuración predeterminada |
preventBodyDrop | boolean | Previene que imágenes arrastradas fuera del componente se abran en el navegador | true |
label | string | Texto de etiqueta para el input | '' |
uploadText | string | Texto del tooltip de carga | 'Seleccionar imagen' |
objectFit | 'contain' | 'cover' | Modo de ajuste de la imagen en preview | 'cover' |
Outputs
| Evento | Tipo | Descripción |
|---|---|---|
focus | void | Declarado, pero nunca se emite: la plantilla no lo enlaza |
blur | void | Declarado, pero nunca se emite: la plantilla no lo enlaza |
onSelect | File | Emite cuando se selecciona una imagen (después de optimización si está habilitada) |
onClear | File | Emite cuando se elimina una imagen nueva (objeto File) |
onClearInstance | string | Emite cuando se elimina una imagen existente (URL) |
Clases del host
tdn-input-image, tdn-input-image--has-value, tdn-input-image--disabled y tdn-input-image--processing, más las de settings.classes.
Atributos HTML
| Atributo | Tipo | Descripción |
|---|---|---|
no-optimize | boolean | Desactiva la optimización automática de imágenes |
accept | string | Lista separada por comas de tipos de imágenes aceptadas (ej: .png,.jpg) |
Configuración
Interfaz TdnInputImageSettings
interface TdnInputImageSettings {
// Textos
removeText?: string; // Texto del tooltip de eliminar
uploadText?: string; // Texto del tooltip de carga
procesingText?: string; // Texto mostrado durante optimización
label?: string; // Etiqueta del input
// Visualización
objectFit?: 'contain' | 'cover'; // Modo de ajuste de imagen
classes?: string; // Clases CSS adicionales
// Tipos aceptados
accept?: string[]; // Array de extensiones aceptadas
// Optimización (basada en ImageCompressor de @tiendana/utils)
optimize?: {
enable?: boolean; // Habilita/deshabilita optimización
maxWidth?: number | null; // Ancho máximo (px)
maxHeight?: number | null; // Alto máximo (px)
quality?: number; // Calidad (0-1)
strict?: boolean; // Modo estricto
checkOrientation?: boolean; // Sin efecto: el componente no lo pasa a ImageCompressor
resize?: 'contain' | 'cover' | 'none'; // Sin efecto: el componente no lo pasa a ImageCompressor
mimeType?: string; // Sin efecto: el componente no lo pasa a ImageCompressor
convertTypes?: string | string[]; // Sin efecto: el componente no lo pasa a ImageCompressor
convertSize?: number; // Sin efecto: el componente no lo pasa a ImageCompressor
};
// Iconos (SVG como string o SafeHtml)
icons?: {
toolbarIcon?: string | SafeHtml; // Icono de la barra de herramientas
upload?: string | SafeHtml; // Icono del botón de carga
clear?: string | SafeHtml; // Icono del botón de eliminar
};
}
Valores Predeterminados
{
removeText: 'Remover imagen',
uploadText: 'Seleccionar imagen',
procesingText: 'Procesando...',
label: '',
objectFit: 'cover',
classes: '',
accept: ['.png', '.jpg', '.jpeg', '.webp'],
optimize: {
enable: true,
strict: true,
maxWidth: 1920,
maxHeight: Infinity,
quality: 1.0
},
icons: {
toolbarIcon: TDN_ICON_TOOLBAR_IMAGE,
upload: TDN_ICON_UPLOAD_IMAGE,
clear: TDN_ICON_CLEAR
}
}
Comportamiento de la optimización
- Con
optimize.enableactivo (por defecto) todas las imágenes, incluidas lasimage/webp, pasan porImageCompressor. Para dejar pasar el archivo tal cual, usano-optimizeuoptimize: { enable: false }. - El archivo emitido se renombra con el nombre en minúsculas.
- Si la compresión falla, se emite el archivo original (también con el nombre en minúsculas).
Ejemplos y Demos
Uso Básico
Ver código
Configuración de Optimización
Ver código
Sin Optimización
Ver código
Object-fit: Contain
Ver código
Imagen Existente (URL)
Ver código
Restricción de Tipos
Ver código
Configuración Personalizada
Ver código
Eventos de Selección y Eliminación
Ver código
Con Validación
Ver código
Ejemplo Completo
Ver código
Buenas Prácticas
Hacer
- Usa optimización automática para reducir tamaño de archivos
- Configura
maxWidthymaxHeightsegún el uso (perfil: 500px, portada: 1920px) - Implementa validación de tamaño en el cliente antes de subir
- Usa
object-fit: containpara logos y elementos que no deben recortarse - Proporciona feedback visual durante la optimización
- Restringe tipos de archivo con
accept
Evitar
- No desactives optimización sin razón justificada
- No permitas imágenes muy grandes sin validación
- No olvides validar dimensiones mínimas cuando sea relevante
- No uses
qualitymuy baja (menor que 0.7) para imágenes importantes - No omitas manejo de errores de optimización
Integración con Backend
Envío con FormData
async uploadImage() {
const formData = new FormData();
const image = this.form.value.avatar;
if (image instanceof File) {
formData.append('avatar', image);
// Enviar al servidor
await fetch('/api/upload-image', {
method: 'POST',
body: formData
});
}
}
Con Información Adicional
async uploadWithMetadata() {
const formData = new FormData();
const image = this.form.value.profilePicture;
if (image instanceof File) {
formData.append('image', image);
formData.append('type', 'profile');
formData.append('userId', this.userId);
await fetch('/api/upload', {
method: 'POST',
body: formData
});
}
}
Accesibilidad
- El componente usa un
<input type="file">nativo con elacceptde la configuración - Los botones tienen atributos
titlepara tooltips descriptivos - El estado
disabledpreviene interacciones cuando está deshabilitado - La imagen de preview tiene alt text apropiado
Personalización Avanzada
Token de Angular
TDN_INPUT_IMAGE_DEFAULT_SETTINGS_TOKEN
Token de inyección para configurar el comportamiento predeterminado de todos los componentes TdnInputImage en la aplicación. Un proveedor reemplaza el objeto completo: parte de TDN_INPUT_IMAGE_DEFAULT_SETTINGS.
import {
TDN_INPUT_IMAGE_DEFAULT_SETTINGS,
TDN_INPUT_IMAGE_DEFAULT_SETTINGS_TOKEN,
TdnInputImageSettings
} from '@tiendana/ngx-core/forms';
import { bootstrapApplication } from '@angular/platform-browser';
const customImageSettings: TdnInputImageSettings = {
...TDN_INPUT_IMAGE_DEFAULT_SETTINGS,
objectFit: 'contain',
optimize: {
...TDN_INPUT_IMAGE_DEFAULT_SETTINGS.optimize,
enable: true,
maxWidth: 1200,
maxHeight: 1200,
quality: 0.85
},
accept: ['.png', '.jpg', '.jpeg', '.webp']
};
bootstrapApplication(AppComponent, {
providers: [
{
provide: TDN_INPUT_IMAGE_DEFAULT_SETTINGS_TOKEN,
useValue: customImageSettings
}
]
});
Configuración a Nivel de Módulo/Componente
Puedes proporcionar configuraciones específicas para un contexto limitado:
import { Component } from '@angular/core';
import {
TDN_INPUT_IMAGE_DEFAULT_SETTINGS,
TDN_INPUT_IMAGE_DEFAULT_SETTINGS_TOKEN
} from '@tiendana/ngx-core/forms';
@Component({
selector: 'app-products-section',
providers: [
{
provide: TDN_INPUT_IMAGE_DEFAULT_SETTINGS_TOKEN,
useValue: {
...TDN_INPUT_IMAGE_DEFAULT_SETTINGS,
optimize: {
...TDN_INPUT_IMAGE_DEFAULT_SETTINGS.optimize,
enable: true,
maxWidth: 800,
maxHeight: 800,
quality: 0.9
}
}
}
],
template: `
<!-- Todos los TdnInputImage aquí heredarán esta configuración -->
`
})
export class ProductsSectionComponent {}
Valores Predeterminados del Token
Si no se proporciona configuración, el componente usa estos valores (exportados también como TDN_INPUT_IMAGE_DEFAULT_SETTINGS; la fábrica del token clona icons, optimize y accept):
{
removeText: 'Remover imagen',
uploadText: 'Seleccionar imagen',
procesingText: 'Procesando...',
label: '',
objectFit: 'cover',
classes: '',
accept: ['.png', '.jpg', '.jpeg', '.webp'],
optimize: {
enable: true,
strict: true,
maxWidth: 1920,
maxHeight: Infinity,
quality: 1.0
},
icons: {
toolbarIcon: TDN_ICON_TOOLBAR_IMAGE,
upload: TDN_ICON_UPLOAD_IMAGE,
clear: TDN_ICON_CLEAR
}
}
Componentes Relacionados
- TdnInputFile - Carga de archivos genéricos
- TdnFormElement - Contenedor de campos de formulario
- tdnControl - Seguimiento de estado con signals
- ImageCompressor - Motor de compresión de imágenes utilizado internamente