Comprehensive collection of business-ready web components for modern web applications
Data components provide high-performance display and manipulation of large datasets. These components support virtualization, sorting, filtering, and advanced interactions for handling complex data scenarios.
Advanced data grid with comprehensive features for displaying and manipulating tabular data.
/**
* High-performance data grid component
* Supports large datasets with virtual scrolling and advanced features
*/
interface Grid extends HTMLElement {
/** Array of data items to display */
items: object[];
/** Array of currently selected items */
selectedItems: object[];
/** Currently active (focused) item */
activeItem: object | null;
/** Array of items with expanded details */
detailsOpenedItems: object[];
/** Enable column reordering */
columnReorderingAllowed: boolean;
/** Enable multi-column sorting */
multiSort: boolean;
/** Height of each row in pixels */
itemHeight: number;
/** Enable all rows selection */
allRowsSelected: boolean;
/** Select a specific item */
selectItem(item: object): void;
/** Deselect a specific item */
deselectItem(item: object): void;
/** Select all visible items */
selectAll(): void;
/** Deselect all items */
deselectAll(): void;
/** Expand item details */
expandItem(item: object): void;
/** Collapse item details */
collapseItem(item: object): void;
/** Clear internal data cache */
clearCache(): void;
/** Scroll to specific item */
scrollToIndex(index: number): void;
/** Recalculate column widths */
recalculateColumnWidths(): void;
}
/**
* Grid column definition
* Defines display and behavior for a data column
*/
interface GridColumn extends HTMLElement {
/** Property path in data items */
path: string;
/** Column header text */
header: string;
/** Column width */
width: string;
/** Minimum column width */
minWidth: string;
/** Maximum column width */
maxWidth: string;
/** Column can be resized */
resizable: boolean;
/** Column is frozen (always visible) */
frozen: boolean;
/** Column is hidden */
hidden: boolean;
/** Text alignment */
textAlign: 'start' | 'center' | 'end';
/** Custom renderer function */
renderer: (root: HTMLElement, column: GridColumn, model: GridItemModel) => void;
}
/**
* Grid item model for renderers
*/
interface GridItemModel {
index: number;
item: object;
selected: boolean;
expanded: boolean;
level: number;
}
/**
* Sortable grid column
*/
interface GridSortColumn extends GridColumn {
/** Sort direction */
direction: 'asc' | 'desc' | null;
/** Sort priority for multi-sort */
sortPriority: number;
}
/**
* Selection column for row selection
*/
interface GridSelectionColumn extends GridColumn {
/** Auto-select rows on click */
autoSelect: boolean;
/** Show select all checkbox in header */
selectAll: boolean;
}
/**
* Tree column for hierarchical data
*/
interface GridTreeColumn extends GridColumn {
/** Path to child items property */
itemHasChildrenPath: string;
/** Path to expanded state property */
itemExpandedPath: string;
}Usage Examples:
import '@vaadin/grid';
import '@vaadin/grid/vaadin-grid-column';
import '@vaadin/grid/vaadin-grid-selection-column';
// Basic grid setup
const grid = document.createElement('vaadin-grid');
grid.items = [
{ name: 'John Doe', email: 'john@example.com', age: 30 },
{ name: 'Jane Smith', email: 'jane@example.com', age: 25 },
{ name: 'Bob Johnson', email: 'bob@example.com', age: 35 }
];
// Add selection column
const selectionColumn = document.createElement('vaadin-grid-selection-column');
selectionColumn.autoSelect = true;
grid.appendChild(selectionColumn);
// Add data columns
const nameColumn = document.createElement('vaadin-grid-column');
nameColumn.path = 'name';
nameColumn.header = 'Name';
nameColumn.width = '200px';
grid.appendChild(nameColumn);
const emailColumn = document.createElement('vaadin-grid-column');
emailColumn.path = 'email';
emailColumn.header = 'Email';
grid.appendChild(emailColumn);
// Custom renderer for actions
const actionColumn = document.createElement('vaadin-grid-column');
actionColumn.header = 'Actions';
actionColumn.renderer = (root, column, model) => {
if (!root.firstElementChild) {
const button = document.createElement('vaadin-button');
button.textContent = 'Edit';
button.addEventListener('click', () => {
console.log('Edit user:', model.item);
});
root.appendChild(button);
}
};
grid.appendChild(actionColumn);
// Handle selection changes
grid.addEventListener('active-item-changed', (e) => {
console.log('Active item:', e.detail.value);
});High-performance list component with virtual scrolling for large datasets.
/**
* Virtualized list component for rendering large datasets
* Only renders visible items for optimal performance
*/
interface VirtualList extends HTMLElement {
/** Array of data items */
items: object[];
/** Custom renderer function for items */
renderer: (root: HTMLElement, list: VirtualList, index: number, item: object) => void;
/** Height of each list item */
itemHeight: number;
/** Number of items to render outside viewport */
overscan: number;
/** Scroll to specific item index */
scrollToIndex(index: number): void;
/** Get first visible item index */
getFirstVisibleIndex(): number;
/** Get last visible item index */
getLastVisibleIndex(): number;
}Usage Examples:
import '@vaadin/virtual-list';
// Large dataset virtual list
const virtualList = document.createElement('vaadin-virtual-list');
// Generate large dataset
const items = Array.from({ length: 100000 }, (_, index) => ({
id: index,
name: `Item ${index}`,
description: `Description for item ${index}`
}));
virtualList.items = items;
// Custom item renderer
virtualList.renderer = (root, list, index, item) => {
if (!root.firstElementChild) {
root.innerHTML = `
<div class="item">
<div class="name"></div>
<div class="description"></div>
</div>
`;
}
const nameEl = root.querySelector('.name');
const descEl = root.querySelector('.description');
nameEl.textContent = item.name;
descEl.textContent = item.description;
};
// Scroll to specific item
setTimeout(() => {
virtualList.scrollToIndex(50000); // Scroll to middle
}, 1000);// Grid with server-side data loading
const setupLazyGrid = (grid: Grid) => {
let cachedItems: Map<number, object> = new Map();
let totalItems = 0;
// Set up data provider
grid.dataProvider = (params, callback) => {
const { page, pageSize, sortOrders, filters } = params;
// Check cache first
const cacheKey = `${page}-${pageSize}`;
if (cachedItems.has(cacheKey)) {
callback(cachedItems.get(cacheKey), totalItems);
return;
}
// Load from server
const queryParams = new URLSearchParams({
page: page.toString(),
size: pageSize.toString(),
sort: sortOrders.map(s => `${s.path},${s.direction}`).join(';'),
filter: JSON.stringify(filters)
});
fetch(`/api/data?${queryParams}`)
.then(response => response.json())
.then(data => {
cachedItems.set(cacheKey, data.items);
totalItems = data.totalCount;
callback(data.items, data.totalCount);
})
.catch(error => {
console.error('Failed to load data:', error);
callback([], 0);
});
};
};// Grid with inline editing capabilities
const setupEditableGrid = (grid: Grid) => {
// Add edit column with custom renderer
const editColumn = document.createElement('vaadin-grid-column');
editColumn.header = 'Name (Editable)';
editColumn.renderer = (root, column, model) => {
if (!root.firstElementChild) {
const textField = document.createElement('vaadin-text-field');
textField.style.width = '100%';
textField.addEventListener('change', (e) => {
// Update the item
model.item[column.path] = e.target.value;
// Trigger update event
grid.dispatchEvent(new CustomEvent('item-changed', {
detail: { item: model.item, path: column.path, value: e.target.value }
}));
});
root.appendChild(textField);
}
const textField = root.firstElementChild as any;
textField.value = model.item[column.path] || '';
};
grid.appendChild(editColumn);
};// Hierarchical data grid
const setupTreeGrid = () => {
const grid = document.createElement('vaadin-grid');
// Hierarchical data
const treeData = [
{
name: 'Frontend',
children: [
{ name: 'React', size: '2.1MB' },
{ name: 'Vue', size: '1.8MB' },
{ name: 'Angular', size: '4.2MB' }
]
},
{
name: 'Backend',
children: [
{ name: 'Node.js', size: '15MB' },
{ name: 'Python', size: '25MB' }
]
}
];
// Flatten tree data for grid
const flattenTree = (items: any[], level = 0): any[] => {
return items.reduce((acc, item) => {
acc.push({ ...item, level, expanded: false });
if (item.children) {
acc.push(...flattenTree(item.children, level + 1));
}
return acc;
}, []);
};
grid.items = flattenTree(treeData);
// Tree column with expand/collapse
const treeColumn = document.createElement('vaadin-grid-tree-column');
treeColumn.path = 'name';
treeColumn.header = 'Name';
treeColumn.itemHasChildrenPath = 'children';
grid.appendChild(treeColumn);
const sizeColumn = document.createElement('vaadin-grid-column');
sizeColumn.path = 'size';
sizeColumn.header = 'Size';
grid.appendChild(sizeColumn);
return grid;
};// Export grid data to various formats
const addExportCapability = (grid: Grid) => {
// Export to CSV
const exportToCsv = () => {
const columns = Array.from(grid.querySelectorAll('vaadin-grid-column'));
const headers = columns.map(col => col.header).join(',');
const rows = grid.items.map(item =>
columns.map(col => item[col.path] || '').join(',')
);
const csv = [headers, ...rows].join('\n');
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'data.csv';
a.click();
URL.revokeObjectURL(url);
};
// Export to JSON
const exportToJson = () => {
const data = JSON.stringify(grid.items, null, 2);
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'data.json';
a.click();
URL.revokeObjectURL(url);
};
// Add export buttons
const toolbar = document.createElement('div');
toolbar.className = 'grid-toolbar';
const csvButton = document.createElement('vaadin-button');
csvButton.textContent = 'Export CSV';
csvButton.addEventListener('click', exportToCsv);
const jsonButton = document.createElement('vaadin-button');
jsonButton.textContent = 'Export JSON';
jsonButton.addEventListener('click', exportToJson);
toolbar.appendChild(csvButton);
toolbar.appendChild(jsonButton);
grid.parentElement?.insertBefore(toolbar, grid);
};Install with Tessl CLI
npx tessl i tessl/npm-vaadin--vaadin