Bootstrap Table es una extensión especializada del framework Bootstrap que transforma tablas HTML estáticas en componentes dinámicos con capacidades avanzadas de manipulación de datos. Esta guía explora su arquitectura interna, métodos de configuración y estrategias de integración en entornos de producción.
Fundamentos Arquitectónicos
El componente opera mediante un sistema de inicialización híbrida que combina atributos data-* con una API programática. Esta dualidad permite adaptar la implementación según las necesidades del proyecto: declarativa para casos simples, imperativa para lógica compleja.
Requisitos de Entorno
Antes de la integración, verifique la disponibilidad de estas dependencias en su pipeline de construcción:
<!-- Dependencias esenciales -->
<link rel="stylesheet" href="dist/bootstrap-table.css">
<script src="dist/jquery.min.js"></script>
<script src="dist/bootstrap.bundle.min.js"></script>
<script src="dist/bootstrap-table.min.js"></script>
Inicialización y Configuración
Método Declarativo
La activación mediante atributos HTML minimiza el código JavaScript necesario:
<table
data-toggle="table"
data-url="/api/inventario"
data-pagination="true"
data-page-size="25"
data-side-pagination="server">
<thead>
<tr>
<th data-field="sku" data-sortable="true">Código SKU</th>
<th data-field="descripcion">Descripción</th>
<th data-field="existencia" data-align="right">Stock</th>
<th data-field="ultima_actualizacion" data-formatter="formatearFecha">Actualizado</th>
</tr>
</thead>
</table>
Método Programático
Para escenarios que requieren lógica dinámica, utilice la interfaz de configuración por objetos:
const opcionesTabla = {
url: '/api/inventario',
method: 'GET',
contentType: 'application/json',
queryParams: function(params) {
return {
limite: params.limit,
desplazamiento: params.offset,
orden: params.sort,
direccion: params.order,
busqueda: params.search
};
},
responseHandler: function(respuesta) {
return {
total: respuesta.total_registros,
rows: respuesta.datos
};
},
columns: [
{field: 'sku', title: 'Código', sortable: true},
{field: 'descripcion', title: 'Producto'},
{field: 'precio', title: 'Precio', formatter: function(valor) {
return '$' + parseFloat(valor).toFixed(2);
}}
]
};
$('#tabla-productos').bootstrapTable(opcionesTabla);
Gestión Avanzada de Datos
Paginación en Servidor
Para conjuntos de datos extensos, implemente paginación delegada al backend mediante el parámetro side-pagination="server". Esto transforma cada interacción de paginación en una petición AJAX parametrizada:
// Estructura de respuesta esperada del servidor
{
"total": 1543,
"rows": [
{"id": 1, "nombre": "Componente A", "categoria": "Electrónica"},
{"id": 2, "nombre": "Componente B", "categoria": "Mecánica"}
]
}
Manipulación de Filas
El componente expone métodos para modificar el estado del DOM sin recargar completamente la tabla:
// Inserción programática
$('#tabla-datos').bootstrapTable('insertRow', {
index: 0,
row: {
id: generarIdUnico(),
nombre: 'Nuevo registro',
estado: 'pendiente'
}
});
// Actualización selectiva
$('#tabla-datos').bootstrapTable('updateByUniqueId', {
id: 42,
row: {estado: 'completado', fecha_modificacion: new Date().toISOString()}
});
// Eliminación condicional
const filasSeleccionadas = $('#tabla-datos').bootstrapTable('getSelections');
filasSeleccionadas.forEach(fila => {
$('#tabla-datos').bootstrapTable('removeByUniqueId', fila.id);
});
Personalización de Renderizado
Formateadores de Columnas
Los formateadores permiten transformar datos brutos en representaciones visuales complejas:
function renderizarEstado(valor, fila, indice) {
const clases = {
'activo': 'badge-success',
'suspendido': 'badge-warning',
'eliminado': 'badge-danger'
};
return `<span class="badge ${clases[valor] || 'badge-secondary'}">${valor.toUpperCase()}</span>`;
}
function renderizarAcciones(valor, fila, indice) {
return `
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary" onclick="editarRegistro(${fila.id})">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-outline-danger" onclick="confirmarEliminacion(${fila.id})">
<i class="fas fa-trash"></i>
</button>
</div>
`;
}
Plantillas de Detalle
Implemente filas expandibles para información complementaria:
$('#tabla-maestra').bootstrapTable({
detailView: true,
detailFormatter: function(indice, fila, elemento) {
return `
<div class="p-3 bg-light">
<h6>Historial de Movimientos</h6>
<table class="table table-sm">
<thead><tr><th>Fecha</th><th>Tipo</th><th>Cantidad</th></tr></thead>
<tbody>
${fila.movimientos.map(m => `
<tr>
<td>${m.fecha}</td>
<td>${m.tipo}</td>
<td class="${m.cantidad > 0 ? 'text-success' : 'text-danger'}">
${m.cantidad > 0 ? '+' : ''}${m.cantidad}
</td>
</tr>
`).join('')}
</tbody>
</table>
</div>
`;
}
});
Integración con Frameworks Modernos
Adaptador para Vue.js
Cree un componente envolvente que sincronice el estado de Bootstrap Table con el sistema de reactividad de Vue:
<template>
<table ref="tablaRef" :data-url="endpoint"></table>
</template>
<script>
import { ref, onMounted, onUnmounted, watch } from 'vue';
export default {
props: ['endpoint', 'columnas', 'configuracion'],
emits: ['fila-seleccionada', 'datos-cargados'],
setup(props, { emit }) {
const tablaRef = ref(null);
let instanciaTabla = null;
onMounted(() => {
instanciaTabla = $(tablaRef.value).bootstrapTable({
...props.configuracion,
columns: props.columnas,
onClickRow: (fila, $elemento, campo) => {
emit('fila-seleccionada', fila);
},
onLoadSuccess: (datos) => {
emit('datos-cargados', datos);
}
});
});
onUnmounted(() => {
$(tablaRef.value).bootstrapTable('destroy');
});
// Exposición de métodos para el componente padre
const recargar = () => {
$(tablaRef.value).bootstrapTable('refresh');
};
const obtenerSeleccionados = () => {
return $(tablaRef.value).bootstrapTable('getSelections');
};
return { tablaRef, recargar, obtenerSeleccionados };
}
};
</script>
Extensiones Especializadas
| Extensión | Fucnionalidad | Activación |
|---|---|---|
bootstrap-table-export |
Exportación a CSV, Excel, PDF | data-show-export="true" |
bootstrap-table-filter-control |
Filtros por columna con inputs | data-filter-control="true" |
bootstrap-table-reorder-columns |
Reordenamiento drag-and-drop | data-reorderable-columns="true" |
bootstrap-table-fixed-columns |
Congelamiento de columnas laterales | data-fixed-columns="true" |
Optimización de Rendimiento
Para tablas con más de 1000 registros, aplique estas estrategias:
// Deshabilitar animaciones durante operaciones masivas
$('#tabla-optimizada').bootstrapTable('togglePagination', false);
// Procesamiento en lotes para actualizaciones
function actualizarLote(cambios) {
const tamañoLote = 100;
for (let i = 0; i < cambios.length; i += tamañoLote) {
const lote = cambios.slice(i, i + tamañoLote);
setTimeout(() => {
lote.forEach(c => {
$('#tabla-optimizada').bootstrapTable('updateByUniqueId', {
id: c.id,
row: c.datos
});
});
}, 0);
}
}
// Liberación de memoria al destruir
window.addEventListener('beforeunload', () => {
$('.tabla-dinamica').bootstrapTable('destroy');
});
Depuración y Solución de Problemas
Active el modo de diagnóstico para inspeccionar el flujo de eventos:
$.fn.bootstrapTable.defaults.onAll = function(nombre, args) {
console.log(`[Bootstrap Table] Evento: ${nombre}`, args);
};
Errores comunes y sus resoluciones:
- Datos no renderizan: Verifique que
responseHandlerdevuelva objeto con propiedadestotalyrows - Paginación falla: Confirme que
side-paginationcoincida con la estructura de respuesta del servidor - Eventos no responden: Asegure que los selectoers de jQuery apunten a elementos existentes en el DOM