Data Components

Reference for Spiderly's data table and data view components — paginated lists with filtering, sorting, selection, and Excel export.

Overview

Spiderly provides two components for displaying entity lists:

  • SpiderlyDataTable — paginated table with server-side filtering, sorting, row selection, and Excel export.
  • SpiderlyDataView — card-based list with filtering, useful for visual layouts.

Both support lazy loading (server-side pagination) and work with the generated API service methods.

SpiderlyDataTable

Selector: spiderly-data-table

Advanced paginated table with server-side filtering, sorting, selection, inline editing, and Excel export.

Key Inputs

InputTypeDefaultDescription
colsColumn[]Column definitions (see Column Configuration)
getPaginatedListObservableMethod(filter) => Observable<PaginatedResult>Server fetch method for lazy loading
exportListToExcelObservableMethod(filter) => Observable<any>Method called on "Export to Excel"
deleteItemFromTableObservableMethod(id) => Observable<any>Method called when a row is deleted
deleteListFromTableObservableMethod(ids) => Observable<any>Method called when selected rows are bulk-deleted. When provided, selectionMode is auto-set to 'multiple' and checkboxes appear on each row.
rowsnumberconfig defaultPage size
rowsPerPageOptionsnumber[]config defaultPage-size selector options
selectionMode'single' | 'multiple'Row selection mode
readonlybooleanfalseHides all action buttons
hasLazyLoadbooleantruetrue = server-side; false = client-side
itemsany[]Data rows (only when hasLazyLoad is false)
showAddButtonbooleantrueShow the "Add" button
showExportToExcelButtonbooleantrueShow the "Export" button
showReloadTableButtonbooleanfalseShow the reload-table button
showPaginatorbooleantrueShow the paginator. Pass only when hasLazyLoad is false
showCardWrapperbooleanfalseWrap the table in a card container
navigateOnRowClickbooleanfalseClicking a row navigates to details
additionalFilterIdLongnumberExtra filter ID appended to every request
defaultSortFieldstringSort applied while the user has no sort of their own — shows as a normal header arrow; persisted user sort wins; un-sorting (tri-state header click, Clear filters) returns to it
defaultSortOrder1 | -11Direction for defaultSortField

Key Outputs

OutputPayloadDescription
onLazyLoadFilterFires on every table load (sort, filter, page change)
onTotalRecordsChangenumberFires when the total record count changes
onRowSelectRowClickEventFires when a row is selected
onRowUnselectRowClickEventFires when a row is deselected
onIsAllSelectedChangeAllClickEventFires when the "select all" checkbox changes

Example

import { Component, OnInit } from '@angular/core';
import { TranslocoService } from '@jsverse/transloco';
import { Column, SpiderlyDataTableComponent } from 'spiderly';
import { ApiService } from 'src/app/business/services/api/api.service';

@Component({
  selector: 'product-list',
  templateUrl: './product-list.component.html',
  imports: [SpiderlyDataTableComponent],
})
export class ProductListComponent implements OnInit {
  cols: Column[];

  getProductTableDataObservableMethod = this.apiService.getProductPaginatedList;
  exportProductListToExcelObservableMethod = this.apiService.exportProductListToExcel;
  deleteProductObservableMethod = this.apiService.deleteProduct;
  deleteProductListObservableMethod = this.apiService.deleteProductList;

  constructor(
    private apiService: ApiService,
    private translocoService: TranslocoService,
  ) {}

  ngOnInit() {
    this.cols = [
      { name: this.translocoService.translate('Name'), field: 'name', filterType: 'text' },
      { name: this.translocoService.translate('Price'), field: 'price', filterType: 'numeric' },
      {
        name: this.translocoService.translate('CreatedAt'),
        field: 'createdAt',
        filterType: 'date',
        showMatchModes: true,
      },
    ];
  }
}
<spiderly-data-table
  [cols]="cols"
  [getPaginatedListObservableMethod]="getProductTableDataObservableMethod"
  [exportListToExcelObservableMethod]="exportProductListToExcelObservableMethod"
  [deleteItemFromTableObservableMethod]="deleteProductObservableMethod"
  [deleteListFromTableObservableMethod]="deleteProductListObservableMethod"
></spiderly-data-table>

Column Configuration

Columns are defined using the Column class. Each column maps to a data field and can have filtering, sorting, and custom actions.

PropertyTypeDescription
namestringColumn header label
fieldstringData field name (key from the DTO)
filterType'text' | 'date' | 'multiselect' | 'boolean' | 'numeric' | 'blob'Type of column filter
filterFieldstringAlternate field used for filtering (useful for FK autocomplete fields)
showMatchModesbooleanShow match mode dropdown in the column filter
dropdownOrMultiselectValuesPrimengOption[]Options for multiselect column filters
editablebooleanEnable inline editing for this column
showTimebooleanFor date columns: show time portion
decimalPlacesnumberFor numeric columns: decimal formatting
actionsAction[]Row action buttons (see Actions)
onCellClick(e: CellClickEvent) => voidPer-cell click handler (see Cell click)

Actions

Use the Action class to add buttons to each row:

{
  actions: [
    { field: 'Details', icon: 'pi pi-pencil' },
    { field: 'Delete', icon: 'pi pi-trash' },
    { field: 'custom', name: 'Preview', icon: 'pi pi-eye', onClick: (e) => this.preview(e.id) },
  ],
}

Built-in field values:

  • 'Details' — navigates to the detail page
  • 'Delete' — opens a confirmation dialog and calls deleteItemFromTableObservableMethod
  • Any other value — triggers the onClick callback

Action click payload

The onClick callback receives an ActionClickEvent carrying everything you need to react to the click — including the clicked element, so you can anchor an overlay or popover to it:

PropertyTypeDescription
idnumberThe clicked row's id
rowanyThe full row object the action belongs to
elementHTMLElementThe clicked action element — use as the popover/overlay anchor
originalEventMouseEventThe original DOM click event

For example, to open a PrimeNG popover anchored to the clicked action:

{
  field: 'preview', name: 'Preview', icon: 'pi pi-eye',
  onClick: (e) => {
    this.selectedRow = e.row;
    this.previewPopover.show(e.originalEvent, e.element);
  },
}

Cell click

Set a column's onCellClick to react to clicks on the cell value (as opposed to an action icon) — the mirror of Action.onClick, but for plain value cells. Only columns that define it become clickable (they get a cursor + hover affordance), and the click stops propagation so it does not also trigger navigateOnRowClick. It is not applied to editable cells.

{
  field: 'total', name: 'Total', filterType: 'numeric',
  onCellClick: (e) => {
    this.selectedRow = e.row;
    this.itemsPopover.show(e.originalEvent, e.element);
  },
}

Cell click payload

The onCellClick callback receives a CellClickEvent:

PropertyTypeDescription
idnumberThe clicked row's id (row[idField])
fieldstringThe clicked column's field
rowanyThe full row object
valueanyThe cell's raw value (row[field])
displayValuestringThe formatted text shown in the cell
elementHTMLElementThe clicked <td> — use as the popover/overlay anchor
originalEventMouseEventThe original DOM click event

element is captured at click time on purpose: anchor overlays with it rather than originalEvent.currentTarget, which the DOM resets to null once dispatch ends — so it would already be null inside an async handler that opens the popover after a fetch.

SpiderlyDataView

Selector: spiderly-data-view

Card-based paginated list with custom rendering and filtering. Use this when you want a visual layout instead of a table.

Key Inputs

InputTypeDefaultDescription
filtersDataViewFilter[][]Filter definitions displayed above the card list
getPaginatedListObservableMethod(filter) => Observable<PaginatedResult>Server fetch method
rowsnumber10Page size
itemsany[]Data items (only for non-lazy mode)

Key Outputs

OutputPayloadDescription
onLazyLoadFilterFires on every lazy load (page change, filter change)

Content Projection

Render each card using an ng-template with the #cardBody reference:

<spiderly-data-view
  [getPaginatedListObservableMethod]="getProductListObservableMethod"
  [filters]="filters"
>
  <ng-template #cardBody [templateType]="templateType" let-item let-index="index">
    <div class="p-4 border rounded">
      <h3>{{item.name}}</h3>
      <p>{{item.price | currency}}</p>
    </div>
  </ng-template>
</spiderly-data-view>

The template context provides item (the data object) and index (row index).

Example

import { Component, OnInit } from '@angular/core';
import { TranslocoService } from '@jsverse/transloco';
import { ApiService } from 'src/app/business/services/api/api.service';
import {
  DataViewFilter,
  DataViewCardBody,
  SpiderlyControlsModule,
  SpiderlyDataViewComponent,
  SpiderlyTemplateTypeDirective,
} from 'spiderly';

@Component({
  selector: 'product-data-view',
  templateUrl: './product-data-view.component.html',
  imports: [SpiderlyTemplateTypeDirective, SpiderlyDataViewComponent, SpiderlyControlsModule],
})
export class ProductDataViewComponent implements OnInit {
  templateType?: DataViewCardBody<Product>;
  filters: DataViewFilter<Product>[];

  getProductListObservableMethod = this.apiService.getProductPaginatedList;

  constructor(
    private apiService: ApiService,
    private translocoService: TranslocoService,
  ) {}

  ngOnInit() {
    this.filters = [
      { label: this.translocoService.translate('Name'), type: 'text', field: 'name' },
      {
        label: this.translocoService.translate('Price'),
        type: 'numeric',
        field: 'price',
        showMatchModes: true,
      },
      {
        label: this.translocoService.translate('CreatedAt'),
        type: 'date',
        field: 'createdAt',
        showMatchModes: true,
      },
    ];
  }
}

For a quick-start version of this example, see the Frontend Customization guide.

DataViewFilter

PropertyTypeDescription
labelstringFilter label displayed above the input
fieldstringData field to filter on
filterFieldstringAlternate field for filtering
type'text' | 'date' | 'multiselect' | 'boolean' | 'numeric'Filter input type
showMatchModesbooleanShow match mode dropdown (e.g., equals, greater than)
dropdownOrMultiselectValuesPrimengOption[]Options for multiselect/dropdown filters

Filter Type Behavior

TypeMatch ModesDescription
textContainsText search (contains by default)
numericEquals, Greater Than, Less ThanNumber comparison
dateEquals, Greater Than, Less ThanDate comparison
booleanEqualsTrue/false selection
multiselectInMulti-value selection