Data Grid
<gstock-data-grid>
|
GstockDataGrid
<gstock-data-grid></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'name', title: 'Name' },
{ key: 'email', title: 'Email' },
{ key: 'role', title: 'Role' },
{ key: 'status', title: 'Status', align: 'center' },
];
grid.data = [
{
id: 1,
name: 'John Pérez',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 2,
name: 'Mary García',
email: 'mary@example.com',
role: 'User',
status: 'Active',
},
{
id: 3,
name: 'Charles López',
email: 'charles@example.com',
role: 'Editor',
status: 'Inactive',
},
{
id: 4,
name: 'Ana Rodríguez',
email: 'ana@example.com',
role: 'User',
status: 'Active',
},
{ id: 5, name: 'Luis Martín', email: 'luis@example.com', role: 'Editor', status: 'Active' },
];
});
</script>
Tamaño
Utilice el atributo size para cambiar el tamaño del data grid.
<gstock-data-grid size="small"></gstock-data-grid>
<gstock-data-grid size="medium"></gstock-data-grid>
<gstock-data-grid size="large"></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const gridSmall = document.querySelector('gstock-data-grid[size="small"]');
const gridMedium = document.querySelector('gstock-data-grid[size="medium"]');
const gridLarge = document.querySelector('gstock-data-grid[size="large"]');
const columns = [
{ key: 'name', title: 'Name' },
{ key: 'role', title: 'Role' },
{ key: 'status', title: 'Status' },
];
const data = [
{ id: 1, name: 'John Doe', role: 'Admin', status: 'Active' },
{ id: 2, name: 'Jane Smith', role: 'User', status: 'Active' },
{ id: 3, name: 'Mike Johnson', role: 'Editor', status: 'Inactive' },
];
gridSmall.columns = columns;
gridSmall.data = data;
gridMedium.columns = columns;
gridMedium.data = data;
gridLarge.columns = columns;
gridLarge.data = data;
});
</script>
Columnas
Utilice JavaScript para configurar columnas y datos programáticamente.
<gstock-data-grid></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{
key: 'name',
title: 'Full Name',
sortable: true,
width: '250px',
align: 'left',
},
{
key: 'email',
title: 'Email Address',
sortable: true,
width: '250px',
type: 'text',
},
{
key: 'age',
title: 'Age',
sortable: true,
width: '80px',
align: 'center',
type: 'number',
},
{
key: 'active',
title: 'Active',
sortable: true,
width: '150px',
align: 'center',
type: 'boolean',
formatter: (value, row) => {
return value ? '✅' : '❌';
},
},
];
grid.data = [
{
id: 1,
name: 'John Doe Smith',
email: 'john.doe@company.com',
age: 32,
active: true,
},
{
id: 2,
name: 'Jane Marie Johnson',
email: 'jane.johnson@company.com',
age: 28,
active: true,
},
{
id: 3,
name: 'Mike Brown Wilson',
email: 'mike.brown@company.com',
age: 35,
active: false,
},
{
id: 4,
name: 'Sarah Davis Miller',
email: 'sarah.davis@company.com',
age: 30,
active: true,
},
{
id: 5,
name: 'David Lee Taylor',
email: 'david.lee@company.com',
age: 26,
active: true,
},
];
});
</script>
Rayado
Utilice el atributo striped para alternar los colores de fondo de las
filas.
<gstock-data-grid striped></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'name', title: 'Name' },
{ key: 'email', title: 'Email' },
{ key: 'role', title: 'Role' },
{ key: 'status', title: 'Status', align: 'center' },
];
grid.data = [
{
id: 1,
name: 'John Pérez',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 2,
name: 'Mary García',
email: 'mary@example.com',
role: 'User',
status: 'Active',
},
{
id: 3,
name: 'Charles López',
email: 'charles@example.com',
role: 'Editor',
status: 'Inactive',
},
{ id: 4, name: 'Ana Rodríguez', email: 'ana@example.com', role: 'User', status: 'Active' },
{ id: 5, name: 'Luis Martín', email: 'luis@example.com', role: 'Editor', status: 'Active' },
];
});
</script>
Con bordes
Utilice el atributo bordered para mostrar bordes en todas las celdas.
<gstock-data-grid bordered></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'name', title: 'Product Name', sortable: true },
{ key: 'category', title: 'Category', sortable: true },
{ key: 'price', title: 'Price', sortable: true, align: 'right' },
{ key: 'inStock', title: 'In Stock', align: 'center' },
{ key: 'rating', title: 'Rating', sortable: true, align: 'center' },
];
grid.data = [
{
id: 1,
name: 'Wireless Headphones',
category: 'Electronics',
price: 99.99,
inStock: true,
rating: 4.5,
},
{
id: 2,
name: 'Coffee Maker',
category: 'Appliances',
price: 129.99,
inStock: false,
rating: 4.2,
},
{
id: 3,
name: 'Yoga Mat',
category: 'Fitness',
price: 29.99,
inStock: true,
rating: 4.7,
},
{
id: 4,
name: 'Smartphone',
category: 'Electronics',
price: 699.99,
inStock: true,
rating: 4.3,
},
{
id: 5,
name: 'Running Shoes',
category: 'Sports',
price: 89.99,
inStock: false,
rating: 4.1,
},
{ id: 6, name: 'Desk Lamp', category: 'Home', price: 39.99, inStock: true, rating: 4.0 },
{ id: 7, name: 'Backpack', category: 'Travel', price: 59.99, inStock: true, rating: 4.4 },
{
id: 8,
name: 'Water Bottle',
category: 'Sports',
price: 19.99,
inStock: true,
rating: 4.6,
},
];
});
</script>
Efecto hover
Utilice el atributo hoverable para agregar efectos de hover en las
filas.
<gstock-data-grid hoverable></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'role', title: 'Role', sortable: true },
{ key: 'status', title: 'Status', sortable: true, align: 'center' },
];
grid.data = [
{
id: 1,
name: 'John Pérez',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 2,
name: 'Mary García',
email: 'mary@example.com',
role: 'User',
status: 'Active',
},
{
id: 3,
name: 'Charles López',
email: 'charles@example.com',
role: 'Editor',
status: 'Inactive',
},
{
id: 4,
name: 'Ana Rodríguez',
email: 'ana@example.com',
role: 'User',
status: 'Active',
},
{
id: 5,
name: 'Luis Martín',
email: 'luis@example.com',
role: 'Editor',
status: 'Active',
},
];
});
</script>
Compacto
Utilice el atributo compact para mostrar el data grid con un diseño más
compacto.
<gstock-data-grid size="small" compact></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
// Configure columns
grid.columns = [
{ key: 'id', title: 'ID', sortable: true, width: '60px' },
{ key: 'code', title: 'Code', sortable: true, width: '100px' },
{ key: 'name', title: 'Item Name', sortable: true },
{
key: 'quantity',
title: 'Qty',
sortable: true,
type: 'number',
align: 'center',
width: '80px',
},
{ key: 'unit', title: 'Unit', sortable: true, width: '80px' },
{
key: 'price',
title: 'Price',
sortable: true,
type: 'currency',
align: 'center',
width: '100px',
},
{
key: 'total',
title: 'Total',
sortable: true,
type: 'currency',
align: 'center',
width: '100px',
},
{
key: 'status',
title: 'Status',
sortable: true,
width: '150px',
},
];
const sampleData = [
{
id: 1,
code: 'ITM001',
name: 'Widget A',
quantity: 25,
unit: 'pcs',
price: 12.5,
total: 312.5,
status: 'Active',
},
{
id: 2,
code: 'ITM002',
name: 'Component B',
quantity: 50,
unit: 'pcs',
price: 8.75,
total: 437.5,
status: 'Active',
},
{
id: 3,
code: 'ITM003',
name: 'Part C',
quantity: 100,
unit: 'pcs',
price: 3.2,
total: 320.0,
status: 'Low Stock',
},
{
id: 4,
code: 'ITM004',
name: 'Assembly D',
quantity: 15,
unit: 'sets',
price: 45.0,
total: 675.0,
status: 'Active',
},
{
id: 5,
code: 'ITM005',
name: 'Tool E',
quantity: 8,
unit: 'pcs',
price: 125.0,
total: 1000.0,
status: 'Active',
},
{
id: 6,
code: 'ITM006',
name: 'Material F',
quantity: 200,
unit: 'kg',
price: 2.25,
total: 450.0,
status: 'Active',
},
{
id: 7,
code: 'ITM007',
name: 'Equipment G',
quantity: 3,
unit: 'units',
price: 850.0,
total: 2550.0,
status: 'Reserved',
},
{
id: 8,
code: 'ITM008',
name: 'Supply H',
quantity: 75,
unit: 'boxes',
price: 15.6,
total: 1170.0,
status: 'Active',
},
{
id: 9,
code: 'ITM009',
name: 'Kit I',
quantity: 12,
unit: 'sets',
price: 78.9,
total: 946.8,
status: 'Discontinued',
},
{
id: 10,
code: 'ITM010',
name: 'Module J',
quantity: 30,
unit: 'pcs',
price: 28.4,
total: 852.0,
status: 'Active',
},
];
grid.data = sampleData;
});
</script>
Seleccionable
Utilice el atributo selectable para habilitar la selección de una sola
fila con casillas de verificación. Solo se puede seleccionar una fila a la vez.
<div class="selection-actions">
<gstock-button id="clear-selection-btn" color="secondary" variant="outlined">
Clear Selection
</gstock-button>
<gstock-button id="perform-action-btn" color="primary">Action on Selected</gstock-button>
</div>
<div class="selection-info">
<div id="selection-info">Selected: <strong>0</strong> rows</div>
</div>
<gstock-data-grid selectable></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
const selectionInfo = document.querySelector('#selection-info');
const clearSelectionBtn = document.querySelector('#clear-selection-btn');
const performActionBtn = document.querySelector('#perform-action-btn');
grid.columns = [
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'role', title: 'Role', sortable: true },
{ key: 'status', title: 'Status', sortable: true, align: 'center' },
];
grid.data = [
{
id: 1,
name: 'John Pérez',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 2,
name: 'Mary García',
email: 'mary@example.com',
role: 'User',
status: 'Active',
},
{
id: 3,
name: 'Charles López',
email: 'charles@example.com',
role: 'Editor',
status: 'Inactive',
},
{
id: 4,
name: 'Ana Rodríguez',
email: 'ana@example.com',
role: 'User',
status: 'Active',
},
{
id: 5,
name: 'Luis Martín',
email: 'luis@example.com',
role: 'Editor',
status: 'Active',
},
];
grid.addEventListener('gstock-data-grid-selection-change-event', e => {
updateSelectionInfo();
});
function updateSelectionInfo() {
const selectedRows = grid.getSelectedRows();
const count = selectedRows.length;
selectionInfo.innerHTML = `Selected: <strong>${count}</strong> ${count === 1 ? 'row' : 'rows'}`;
}
function clearSelection() {
grid.deselectAll();
}
function performAction() {
const selectedRows = grid.getSelectedRows();
if (selectedRows.length === 0) {
alert('Please select one row to perform an action.');
return;
}
const selectedRow = selectedRows[0]; // Only one row should be selected
alert(`Action performed on: ${selectedRow.name}`);
}
clearSelectionBtn.addEventListener('click', clearSelection);
performActionBtn.addEventListener('click', performAction);
updateSelectionInfo();
});
</script>
<style>
.selection-info {
background: #f8f9fa;
padding: 1rem;
border-radius: 4px;
margin: 1rem 0;
border-left: 4px solid #007bff;
font-size: 14px;
}
.selection-actions {
margin: 1rem 0;
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.selection-actions button {
padding: 0.5rem 1rem;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
}
.selection-actions button:hover {
background: #f8f9fa;
}
.selection-actions button.primary {
background: #007bff;
color: white;
border-color: #007bff;
}
.selection-actions button.primary:hover {
background: #0056b3;
}
</style>
Multi-selección
Combine los atributos selectable y multi-select para
permitir la selección de varias filas. Aparecerá un checkbox en el encabezado para
seleccionar o deseleccionar todas las filas.
<div class="selection-actions">
<gstock-button id="select-all-btn" color="secondary" variant="outlined">
Select All
</gstock-button>
<gstock-button id="clear-selection-btn" color="secondary" variant="outlined">
Clear Selection
</gstock-button>
<gstock-button id="perform-action-btn" color="primary" disabled>Action on Selected</gstock-button>
</div>
<div class="selection-info">
<div id="selection-info">Selected: <strong>0</strong> rows</div>
</div>
<gstock-data-grid selectable multi-select></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
const selectionInfo = document.querySelector('#selection-info');
const selectAllBtn = document.querySelector('#select-all-btn');
const clearSelectionBtn = document.querySelector('#clear-selection-btn');
const performActionBtn = document.querySelector('#perform-action-btn');
grid.columns = [
{ key: 'name', title: 'Name' },
{ key: 'email', title: 'Email' },
{ key: 'role', title: 'Role' },
{ key: 'status', title: 'Status', align: 'center' },
];
grid.data = [
{
id: 1,
name: 'John Doe',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 2,
name: 'Jane Smith',
email: 'jane@example.com',
role: 'User',
status: 'Active',
},
{
id: 3,
name: 'Mike Johnson',
email: 'mike@example.com',
role: 'Editor',
status: 'Inactive',
},
{ id: 4, name: 'Sarah Wilson', email: 'sarah@example.com', role: 'User', status: 'Active' },
{ id: 5, name: 'David Brown', email: 'david@example.com', role: 'Editor', status: 'Active' },
];
// Listen for selection changes
grid.addEventListener('gstock-data-grid-selection-change-event', event => {
const selectedCount = event.detail.selectedData.length;
selectionInfo.innerHTML = `Selected: <strong>${selectedCount}</strong> rows`;
console.log('Selected rows:', event.detail.selectedData);
});
// Button event handlers
selectAllBtn.addEventListener('click', () => {
grid.selectAll();
console.log('Select All clicked');
});
clearSelectionBtn.addEventListener('click', () => {
grid.deselectAll();
});
performActionBtn.addEventListener('click', () => {
const selected = grid.getSelectedRows();
if (selected.length > 0) {
alert(
`Performing action on ${selected.length} selected rows:\n${selected.map(row => row.name).join(', ')}`,
);
} else {
alert('No rows selected');
}
});
});
</script>
<style>
.selection-actions {
margin-bottom: 1rem;
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
}
.selection-info {
margin-bottom: 1rem;
padding: 0.5rem;
background-color: var(--gstock-color-neutral-50);
border: 1px solid var(--gstock-color-neutral-200);
border-radius: var(--gstock-border-radius-medium);
}
#selection-info {
margin: 0;
font-size: var(--gstock-legacy-font-size-small);
}
</style>
Ordenable
Utilice el atributo sortable para habilitar la funcionalidad de
ordenamiento de columnas.
<gstock-data-grid sortable></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'role', title: 'Role', sortable: true },
{ key: 'status', title: 'Status', sortable: true, align: 'center' },
{ key: 'lastLogin', title: 'Last Login', sortable: true, type: 'date' },
];
grid.data = [
{
id: 1,
name: 'John Pérez',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
lastLogin: '2024-01-15',
},
{
id: 2,
name: 'Mary García',
email: 'mary@example.com',
role: 'User',
status: 'Active',
lastLogin: '2024-01-14',
},
{
id: 3,
name: 'Charles López',
email: 'charles@example.com',
role: 'Editor',
status: 'Inactive',
lastLogin: '2024-01-10',
},
{
id: 4,
name: 'Ana Rodríguez',
email: 'ana@example.com',
role: 'User',
status: 'Active',
lastLogin: '2024-01-16',
},
{
id: 5,
name: 'Luis Martín',
email: 'luis@example.com',
role: 'Editor',
status: 'Active',
lastLogin: '2024-01-12',
},
];
// Listen for sort changes
grid.addEventListener('gstock-sort-change', event => {
console.log('Sort changed:', event.detail);
});
});
</script>
Filtrable
Utilice el atributo filterable para habilitar el filtrado de columnas.
<div class="filter-controls">
<div class="filter-group">
<gstock-input
type="text"
id="name-filter"
label="Name Filter"
placeholder="Search by name..."></gstock-input>
</div>
<div class="filter-group">
<gstock-select id="department-filter" label="Department">
<gstock-option value="">All Departments</gstock-option>
<gstock-option value="Engineering">Engineering</gstock-option>
<gstock-option value="Marketing">Marketing</gstock-option>
<gstock-option value="Sales">Sales</gstock-option>
<gstock-option value="HR">HR</gstock-option>
<gstock-option value="Finance">Finance</gstock-option>
</gstock-select>
</div>
<div class="filter-group">
<gstock-input
type="number"
id="salary-min"
placeholder="0"
min="0"
step="1000"
label="Min Salary"></gstock-input>
</div>
<div class="filter-group">
<gstock-input
type="number"
id="salary-max"
placeholder="200000"
min="0"
step="1000"
label="Max Salary"></gstock-input>
</div>
<div class="filter-actions">
<gstock-button id="apply-filters-btn" class="primary">Apply Filters</gstock-button>
<gstock-button id="clear-filters-btn">Clear All</gstock-button>
</div>
</div>
<div class="filter-status" id="filter-status">Showing all 12 records</div>
<gstock-data-grid filterable></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
const filterStatus = document.querySelector('#filter-status');
const applyFiltersBtn = document.querySelector('#apply-filters-btn');
const clearFiltersBtn = document.querySelector('#clear-filters-btn');
// Configure columns
grid.columns = [
{ key: 'id', title: 'ID', sortable: true, width: '60px' },
{ key: 'name', title: 'Employee Name', sortable: true, filterable: true },
{ key: 'department', title: 'Department', sortable: true, filterable: true },
{ key: 'position', title: 'Position', sortable: true },
{ key: 'salary', title: 'Salary', sortable: true, align: 'right' },
{ key: 'startDate', title: 'Start Date', sortable: true, type: 'date' },
{ key: 'email', title: 'Email', sortable: true, filterable: true },
];
const originalData = [
{
id: 1,
name: 'John Smith',
department: 'Engineering',
position: 'Software Engineer',
salary: 85000,
startDate: '2023-01-15',
email: 'john.smith@company.com',
},
{
id: 2,
name: 'Sarah Johnson',
department: 'Marketing',
position: 'Marketing Manager',
salary: 75000,
startDate: '2022-11-20',
email: 'sarah.johnson@company.com',
},
{
id: 3,
name: 'Mike Davis',
department: 'Sales',
position: 'Sales Representative',
salary: 55000,
startDate: '2023-03-10',
email: 'mike.davis@company.com',
},
{
id: 4,
name: 'Emily Chen',
department: 'Engineering',
position: 'Senior Developer',
salary: 95000,
startDate: '2021-09-05',
email: 'emily.chen@company.com',
},
{
id: 5,
name: 'David Wilson',
department: 'HR',
position: 'HR Specialist',
salary: 60000,
startDate: '2022-07-12',
email: 'david.wilson@company.com',
},
{
id: 6,
name: 'Lisa Anderson',
department: 'Finance',
position: 'Financial Analyst',
salary: 70000,
startDate: '2023-02-28',
email: 'lisa.anderson@company.com',
},
{
id: 7,
name: 'Chris Taylor',
department: 'Engineering',
position: 'DevOps Engineer',
salary: 88000,
startDate: '2022-12-01',
email: 'chris.taylor@company.com',
},
{
id: 8,
name: 'Amanda Brown',
department: 'Marketing',
position: 'Content Specialist',
salary: 52000,
startDate: '2023-04-18',
email: 'amanda.brown@company.com',
},
{
id: 9,
name: 'Robert Lee',
department: 'Sales',
position: 'Sales Manager',
salary: 82000,
startDate: '2021-08-30',
email: 'robert.lee@company.com',
},
{
id: 10,
name: 'Jennifer White',
department: 'Finance',
position: 'Senior Accountant',
salary: 78000,
startDate: '2022-05-15',
email: 'jennifer.white@company.com',
},
{
id: 11,
name: 'Kevin Martinez',
department: 'Engineering',
position: 'Tech Lead',
salary: 105000,
startDate: '2020-11-12',
email: 'kevin.martinez@company.com',
},
{
id: 12,
name: 'Michelle Garcia',
department: 'HR',
position: 'HR Manager',
salary: 85000,
startDate: '2021-06-08',
email: 'michelle.garcia@company.com',
},
];
grid.data = originalData;
grid.addEventListener('gstock-filter-change', e => {
updateFilterStatus();
});
function applyFilters() {
const nameFilter = document.querySelector('#name-filter').value.toLowerCase();
const departmentFilter = document.querySelector('#department-filter').value;
const salaryMin = parseInt(document.querySelector('#salary-min').value) || 0;
const salaryMax = parseInt(document.querySelector('#salary-max').value) || Infinity;
let filteredData = originalData.filter(item => {
const nameMatch = !nameFilter || item.name.toLowerCase().includes(nameFilter);
const departmentMatch = !departmentFilter || item.department === departmentFilter;
const salaryMatch = item.salary >= salaryMin && item.salary <= salaryMax;
return nameMatch && departmentMatch && salaryMatch;
});
grid.data = filteredData;
updateFilterStatus();
}
function clearFilters() {
document.querySelector('#name-filter').value = '';
document.querySelector('#department-filter').value = '';
document.querySelector('#salary-min').value = '';
document.querySelector('#salary-max').value = '';
grid.data = originalData;
grid.clearFilters();
updateFilterStatus();
}
function updateFilterStatus() {
const currentData = grid.data || [];
const total = originalData.length;
const showing = currentData.length;
if (showing === total) {
filterStatus.textContent = `Showing all ${total} records`;
} else {
filterStatus.textContent = `Showing ${showing} of ${total} records (filtered)`;
}
}
applyFiltersBtn.addEventListener('click', applyFilters);
clearFiltersBtn.addEventListener('click', clearFilters);
document.querySelector('#name-filter').addEventListener('input', applyFilters);
document.querySelector('#department-filter').addEventListener('change', applyFilters);
document.querySelector('#salary-min').addEventListener('input', applyFilters);
document.querySelector('#salary-max').addEventListener('input', applyFilters);
updateFilterStatus();
});
</script>
<style>
.filter-controls {
background: #f8f9fa;
padding: 1rem;
border-radius: 4px;
margin: 1rem 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 1rem;
}
.filter-group {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.filter-group label {
font-weight: 600;
font-size: 14px;
color: #333;
}
.filter-group input,
.filter-group select {
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 14px;
}
.filter-actions {
display: flex;
gap: 0.5rem;
align-items: end;
}
.filter-actions button {
padding: 0.5rem 1rem;
border: 1px solid #ddd;
background: white;
border-radius: 4px;
cursor: pointer;
font-size: 14px;
height: fit-content;
}
.filter-actions button:hover {
background: #f8f9fa;
}
.filter-actions button.primary {
background: #007bff;
color: white;
border-color: #007bff;
}
.filter-actions button.primary:hover {
background: #0056b3;
}
.filter-status {
margin: 1rem 0;
padding: 0.5rem;
background: #e3f2fd;
border-radius: 4px;
font-size: 14px;
}
</style>
Paginación
Utilice el atributo paginated para habilitar paginación virtual para
datasets.
<gstock-data-grid paginated page-size="3"></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'role', title: 'Role', sortable: true },
{ key: 'status', title: 'Status', sortable: true, align: 'center' },
];
grid.data = [
{
id: 1,
name: 'John Doe',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 2,
name: 'Jane Smith',
email: 'jane@example.com',
role: 'User',
status: 'Active',
},
{
id: 3,
name: 'Mike Johnson',
email: 'mike@example.com',
role: 'Editor',
status: 'Inactive',
},
{ id: 4, name: 'Sarah Wilson', email: 'sarah@example.com', role: 'User', status: 'Active' },
{ id: 5, name: 'David Brown', email: 'david@example.com', role: 'Editor', status: 'Active' },
{ id: 6, name: 'Emily Davis', email: 'emily@example.com', role: 'User', status: 'Active' },
{
id: 7,
name: 'Michael Miller',
email: 'michael@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 8,
name: 'Laura Taylor',
email: 'laura@example.com',
role: 'Editor',
status: 'Inactive',
},
{
id: 9,
name: 'Robert Anderson',
email: 'robert@example.com',
role: 'User',
status: 'Active',
},
{
id: 10,
name: 'Jessica Thompson',
email: 'jessica@example.com',
role: 'Editor',
status: 'Active',
},
];
});
</script>
Combine los atributos paginated junto a los atributos
total-pages y total-items para utilizar paginación del
servidor y cargar datos bajo demanda.
<gstock-data-grid
paginated
page-size="5"
current-page="1"
total-pages="10"
total-items="50"></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'id', title: 'ID', sortable: true, width: '80px' },
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'department', title: 'Department', sortable: true },
{ key: 'joinDate', title: 'Join Date', sortable: true, align: 'center' },
];
function loadPageData(page, isInitialLoad = false) {
if (isInitialLoad) {
grid.loading = true;
}
setTimeout(() => {
const pageData = [];
const startId = (page - 1) * 5 + 1;
for (let i = 0; i < 5; i++) {
const id = startId + i;
pageData.push({
id: id,
name: `Employee ${id}`,
email: `employee${id}@company.com`,
department: ['Engineering', 'Marketing', 'Sales', 'HR', 'Finance'][id % 5],
joinDate: `2023-${String(Math.floor(Math.random() * 12) + 1).padStart(2, '0')}-${String(Math.floor(Math.random() * 28) + 1).padStart(2, '0')}`,
});
}
grid.data = pageData;
grid.loading = false;
}, 500);
}
grid.addEventListener('gstock-page-change-event', event => {
loadPageData(event.detail.currentPage, false);
});
loadPageData(1, true);
});
</script>
Redimensionable
Utilice el atributo resizable para habilitar la función de
redimensionamiento de columnas.
<gstock-data-grid resizable bordered hoverable></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
// Configure columns with different resizable settings
grid.columns = [
{
key: 'id',
title: 'ID',
width: '60px',
resizable: true,
sortable: true,
},
{
key: 'name',
title: 'Product Name',
resizable: true,
sortable: true,
},
{
key: 'category',
title: 'Category',
width: '200px',
resizable: true,
sortable: true,
},
{
key: 'price',
title: 'Price',
width: '150px',
align: 'right',
resizable: true,
sortable: true,
formatter: value => `€${parseFloat(value).toFixed(2)}`,
},
{
key: 'stock',
title: 'Stock',
width: '150px',
align: 'center',
resizable: true,
sortable: true,
},
{
key: 'status',
title: 'Status',
width: '200px',
align: 'center',
resizable: false, // This column cannot be resized
formatter: value => {
const color =
value === 'Available' ? 'success' : value === 'Low Stock' ? 'warning' : 'danger';
return `<gstock-badge color="${color}">${value}</gstock-badge>`;
},
},
];
// Sample data
grid.data = [
{
id: 1,
name: 'Laptop Dell XPS 13',
category: 'Electronics',
price: 999.99,
stock: 15,
status: 'Available',
},
{
id: 2,
name: 'Wireless Mouse Logitech',
category: 'Accessories',
price: 29.99,
stock: 3,
status: 'Low Stock',
},
{
id: 3,
name: 'Mechanical Keyboard',
category: 'Accessories',
price: 79.99,
stock: 0,
status: 'Out of Stock',
},
{
id: 4,
name: 'Monitor 4K Samsung',
category: 'Electronics',
price: 349.99,
stock: 8,
status: 'Available',
},
{
id: 5,
name: 'USB-C Hub',
category: 'Accessories',
price: 49.99,
stock: 12,
status: 'Available',
},
{
id: 6,
name: 'Webcam HD',
category: 'Electronics',
price: 89.99,
stock: 2,
status: 'Low Stock',
},
];
// Listen for column resize events
grid.addEventListener('gstock-data-grid-column-resize-event', event => {
console.log('Column resized:', {
column: event.detail.column,
newWidth: event.detail.width,
allColumnWidths: event.detail.columnWidths,
});
});
});
</script>
Estado de carga
Utilice el atributo loading para mostrar un indicador de carga.
Mientras el estado de carga está activo, se muestra un mensaje indicando el estado.
<div class="demo-controls">
<gstock-button id="load-data-btn" color="primary">Load Data</gstock-button>
<gstock-button id="slow-load-btn" color="secondary" variant="outlined">
Slow Load (3s )</gstock-button
>
<gstock-button id="simulate-error-btn" color="secondary" variant="outlined">
Simulate Error
</gstock-button>
<gstock-button id="clear-data-btn" color="secondary" variant="outlined">Clear Data</gstock-button>
</div>
<div class="status-indicator" id="status-indicator">Ready to load data</div>
<gstock-data-grid loading></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
const statusIndicator = document.querySelector('#status-indicator');
const loadDataBtn = document.querySelector('#load-data-btn');
const slowLoadBtn = document.querySelector('#slow-load-btn');
const simulateErrorBtn = document.querySelector('#simulate-error-btn');
const clearDataBtn = document.querySelector('#clear-data-btn');
grid.columns = [
{ key: 'id', title: 'ID', sortable: true, width: '80px' },
{ key: 'title', title: 'Title', sortable: true },
{ key: 'author', title: 'Author', sortable: true },
{ key: 'category', title: 'Category', sortable: true },
{ key: 'publishDate', title: 'Date', sortable: true, type: 'date' },
];
const sampleData = [
{
id: 1,
title: 'Introduction to Web Components',
author: 'John Pérez',
category: 'Technology',
publishDate: '2024-01-15',
},
{
id: 2,
title: 'CSS Best Practices',
author: 'Mary García',
category: 'Design',
publishDate: '2024-01-14',
},
{
id: 3,
title: 'Modern JavaScript',
author: 'Charles López',
category: 'Programming',
publishDate: '2024-01-13',
},
{
id: 4,
title: 'UX/UI Design Principles',
author: 'Ana Rodríguez',
category: 'Design',
publishDate: '2024-01-12',
},
{
id: 5,
title: 'Performance Optimization',
author: 'Luis Martín',
category: 'Technology',
publishDate: '2024-01-11',
},
];
function updateStatus(message, type = '') {
statusIndicator.textContent = message;
statusIndicator.className = `status-indicator ${type}`;
}
function loadData() {
grid.loading = true;
updateStatus('Loading data...', 'loading');
setTimeout(() => {
grid.data = sampleData;
grid.loading = false;
updateStatus('Data loaded successfully', 'loaded');
}, 1000);
}
function simulateSlowLoad() {
grid.loading = true;
updateStatus('Loading data (slow)...', 'loading');
setTimeout(() => {
grid.data = sampleData;
grid.loading = false;
updateStatus('Data loaded after 3 seconds', 'loaded');
}, 3000);
}
function simulateError() {
grid.loading = true;
updateStatus('Trying to load data...', 'loading');
setTimeout(() => {
grid.loading = false;
grid.data = [];
updateStatus('Error loading data', 'error');
}, 2000);
}
function clearData() {
grid.data = [];
grid.loading = false;
updateStatus('Data cleared', '');
}
loadDataBtn.addEventListener('click', loadData);
slowLoadBtn.addEventListener('click', simulateSlowLoad);
simulateErrorBtn.addEventListener('click', simulateError);
clearDataBtn.addEventListener('click', clearData);
updateStatus('Ready to load data', '');
});
</script>
<style>
.status-indicator {
margin: 1rem 0;
padding: 0.75rem;
border-radius: 4px;
font-weight: 500;
}
.status-indicator.loading {
background: #fff3cd;
color: #856404;
border: 1px solid #ffeaa7;
}
.status-indicator.loaded {
background: #d4edda;
color: #155724;
border: 1px solid #c3e6cb;
}
.status-indicator.error {
background: #f8d7da;
color: #721c24;
border: 1px solid #f5c6cb;
}
</style>
Utilice el atributo loading-message para personalizar el mensaje del
estado de carga.
<gstock-data-grid loading-message="Custom loading message..." loading></gstock-data-grid>
Estado vacío
El data grid muestra un mensaje indicando el estado cuando no hay datos disponibles.
<div class="demo-controls">
<gstock-button id="add-data-btn" color="primary">Add Data</gstock-button>
<gstock-button id="clear-data-btn" color="secondary" variant="outlined">
Clear Data
</gstock-button>
</div>
<gstock-data-grid></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
const addDataBtn = document.querySelector('#add-data-btn');
const clearDataBtn = document.querySelector('#clear-data-btn');
grid.columns = [
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'role', title: 'Role', sortable: true },
{ key: 'status', title: 'Status', sortable: true, align: 'center' },
];
grid.data = [];
const sampleData = [
{
id: 1,
name: 'John Pérez',
email: 'john@example.com',
role: 'Administrator',
status: 'Active',
},
{
id: 2,
name: 'Mary García',
email: 'mary@example.com',
role: 'User',
status: 'Active',
},
{
id: 3,
name: 'Charles López',
email: 'charles@example.com',
role: 'Editor',
status: 'Inactive',
},
];
function addData() {
grid.data = [...sampleData];
console.log('Data added:', grid.data.length, 'records');
}
function clearData() {
grid.data = [];
console.log('Data cleared, current records:', grid.data.length);
if (grid.requestUpdate) {
grid.requestUpdate();
}
}
addDataBtn.addEventListener('click', addData);
clearDataBtn.addEventListener('click', clearData);
});
</script>
Utilice el atributo empty-message para personalizar el mensaje del
estado vacío.
<gstock-data-grid empty-message="Custom empty message"></gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
grid.columns = [
{ key: 'name', title: 'Name', sortable: true },
{ key: 'email', title: 'Email', sortable: true },
{ key: 'role', title: 'Role', sortable: true },
{ key: 'status', title: 'Status', sortable: true, align: 'center' },
];
grid.data = [];
});
</script>
Avanzado
Combine múltiples características para una experiencia completa del data grid.
User Management
<gstock-data-grid
striped
hoverable
selectable
multi-select
sortable
filterable
paginated
page-size="5">
<div slot="toolbar">
<div style="display: flex; justify-content: space-between; align-items: center">
<h3 style="margin: 0">User Management</h3>
<div style="display: flex; gap: 8px">
<gstock-button prefix="download" variant="plain" id="export-btn"> Export </gstock-button>
<gstock-button prefix="plus" id="add-btn"> Add User </gstock-button>
</div>
</div>
</div>
<div slot="footer">
<div
style="
display: flex;
justify-content: space-between;
align-items: center;
font-size: 0.875rem;
color: var(--gstock-legacy-color-grayscale-600);
">
<span>Last updated: June 2, 2025</span>
<span id="selection-info">0 items selected</span>
</div>
</div>
</gstock-data-grid>
<script type="module">
customElements.whenDefined('gstock-data-grid').then(() => {
const grid = document.querySelector('gstock-data-grid');
const selectionInfo = document.querySelector('#selection-info');
const exportBtn = document.querySelector('#export-btn');
const addBtn = document.querySelector('#add-btn');
grid.columns = [
{ key: 'name', title: 'Name', sortable: true, filterable: true },
{ key: 'email', title: 'Email', sortable: true, filterable: true },
{
key: 'role',
title: 'Role',
sortable: true,
filterable: true,
formatter: (value, row) => {
const color =
value === 'Administrator' ? 'primary' : value === 'Editor' ? 'warning' : 'neutral';
return `<gstock-badge color="${color}">${value}</gstock-badge>`;
},
},
{
key: 'status',
title: 'Status',
align: 'center',
sortable: true,
filterable: true,
formatter: (value, row) => {
const color = value === 'Active' ? 'success' : 'danger';
const icon = value === 'Active' ? 'check-circle' : 'x-circle';
return `<gstock-icon name="${icon}" style="color: var(--gstock-color-semantic-${color}-500);"></gstock-icon>`;
},
},
{ key: 'lastLogin', title: 'Last Login', sortable: true, type: 'date' },
{
key: 'actions',
title: 'Actions',
align: 'center',
formatter: (value, row) => {
return `
<div style="display: flex; gap: 4px; justify-content: center;">
<gstock-icon-button icon="edit" size="small" variant="outlined" title="Edit">
</gstock-icon-button>
<gstock-icon-button icon="trash" size="small" variant="outlined" color="danger" title="Delete">
</gstock-icon-button>
</div>
`;
},
},
];
// Generate larger dataset
const roles = ['Administrator', 'User', 'Editor'];
const statuses = ['Active', 'Inactive'];
const names = [
'John Pérez',
'Mary García',
'Charles López',
'Ana Rodríguez',
'Luis Martín',
'Elena Ruiz',
'Miguel Sánchez',
'Laura Torres',
'David Herrera',
'Carmen Vega',
'Pedro Morales',
'Sofia Castillo',
'Alejandro Ramos',
'Isabel Jiménez',
'Roberto Silva',
];
grid.data = names.map((name, index) => ({
id: index + 1,
name,
email: `${name.toLowerCase().replace(' ', '.')}@example.com`,
role: roles[index % roles.length],
status: statuses[index % statuses.length],
lastLogin: new Date(2024, 0, 15 - (index % 10)).toISOString().split('T')[0],
}));
grid.addEventListener('gstock-data-grid-selection-change-event', event => {
const count = event.detail.selectedData.length;
selectionInfo.textContent = `${count} item${count !== 1 ? 's' : ''} selected`;
});
exportBtn.addEventListener('click', () => {
const selectedData = grid.getSelectedRows();
console.log('Exporting data:', selectedData.length ? selectedData : grid.data);
alert(`Exporting ${selectedData.length ? selectedData.length : grid.data.length} records...`);
});
addBtn.addEventListener('click', () => {
alert('Open form to add new user...');
});
grid.addEventListener('gstock-row-click', event => {
console.log('Row clicked:', event.detail.row);
});
grid.addEventListener('gstock-sort-change', event => {
console.log('Sort changed:', event.detail);
});
});
</script>