Overview

Datasource

wuic-data-source is the component that manages metadata, data fetching, current state, change tracking, and CRUD sync.

Description

  • Resolves the route (route/hardcodedRoute or URL routing).
  • Loads table/column metadata and publishes state on fetchInfo$.
  • Manages filterInfo, sortInfo, groupInfo, paging (pageSize, currentPage) and cursor paging.
  • Exposes runtime methods for insert/update/delete, batch save, rollback, and export.
  • It is the central point to which wuic-data-repeater, wuic-filter-bar, and wuic-pager connect.

API

Selector:

  • wuic-data-source

Main inputs:

  • route: BehaviorSubject<string>
  • routeFromRouting: boolean
  • hardcodedRoute: string
  • autoload?: boolean
  • loading: BehaviorSubject<boolean>
  • changeTracking?: boolean
  • parentRecord: any
  • parentMetaInfo: MetaInfo
  • parentDatasource: DataSourceComponent
  • componentRef: BehaviorSubject<{ component, id, name, uniqueName }>

Main state/runtime:

  • metaInfo: MetaInfo
  • resultInfo: ResultInfo
  • filterInfo?: FilterInfo
  • sortInfo: SortInfo[]
  • groupInfo: GroupInfo[]
  • aggregationInfo: AggregationInfo[]
  • fetchInfo$: BehaviorSubject<{ resultInfo, metaInfo, filterDescriptor }>
  • datasourceReady$: BehaviorSubject<DataSourceComponent | null>
  • afterFirstLoad$: BehaviorSubject<any>
  • beforeSync$: Subject<DataSourceBeforeSyncEvent> (cancellable)
  • afterSync$: Subject<DataSourceAfterSyncEvent>

Most used runtime methods:

  • fetchData()
  • syncData(entita, original, deleting?, cloning?)
  • addNewRecord(record?)
  • setCurrent(data)
  • clearColumnFilter(col, fetch?)
  • getPendingChanges()
  • hasPendingChanges()
  • batchSave(targetChanges?)
  • rollbackChanges(targetChanges?)
  • exportXls()

Runtime subscriptions/events:

  • fetchInfo$: main data/metadata state stream.
  • datasourceReady$: emitted when the datasource instance is ready.
  • afterFirstLoad$: emitted once on the first useful payload.
  • beforeSync$: emitted before insert/update/delete/clone/batch; you can cancel with event.cancelSync(...).
  • afterSync$: emitted after successful sync.

Compatibility note:

  • The fetchInfo alias (getter/setter) is also available, but the recommended naming is fetchInfo$.

Examples

Basic Example (Hardcoded Route + Autoload)

Snippet 1HTML
<wuic-data-source
  [hardcodedRoute]="'cities'"
  [autoload]="true">
</wuic-data-source>

Master-Detail Example (Nested Datasource)

Snippet 2HTML
<wuic-data-source #masterDs [hardcodedRoute]="'orders'" [autoload]="true"></wuic-data-source>

<wuic-data-source
  [hardcodedRoute]="'order_rows'"
  [parentDatasource]="masterDs"
  [parentRecord]="masterDs.resultInfo?.current"
  [parentMetaInfo]="masterDs.metaInfo"

Operational Example (Manual Fetch + Sync)

Snippet 3ts
await datasource.fetchData();

const row = datasource.addNewRecord({ customer_name: 'ACME' });
await datasource.syncData(row, null, false, false);

Subscriptions Example (Host)

Snippet 4ts
const subs = new Subscription();

subs.add(
  datasource.fetchInfo$.subscribe((info) => {
    if (!info) return;
    console.log('records', info.resultInfo?.dato?.length || 0);
  })

Runtime metaInfo patches via fetchInfo$.subscribe

To modify a nested datasource's metadata at runtime (e.g. mc_hide_in_list, md_inline_cell_editing, md_pageable=false, mc_logic_editable=false) without touching the DB — local patch on the reference cached by MetadataProviderService, latest-wins, single-dialog scenario — subscribe to the data-source's fetchInfo$:

Snippet 5ts
private bindNestedMetaPatches(): void {
  if (!this.scadenzeDs) return;
  const ESSENTIAL = new Set(['data_scadenza', 'importo', 'pagamento_id', 'stato', 'note']);
  const sub = this.scadenzeDs.fetchInfo$.subscribe((info) => {
    const route = this.scadenzeDs?.route?.value;
    if (!info || route !== info.metaInfo?.tableMetadata?.md_route_name) return;
    const cols: any[] = info.metaInfo?.columnMetadata || [];

Scope: session-only + instance-only. The patch survives only until the MetadataProviderService cache is invalidated or the component is destroyed. Useful when a custom form needs a different representation of a nested grid compared to the standalone rendering.

When NOT to use runtime patches: for changes targeted at all instances of the route (including standalone <route>/list) → direct SQL patch on metadata; for changes persisting across restarts → direct SQL on metadata.

Multiple <wuic-data-source> in the same component

When a custom component contains more than one <wuic-data-source> (e.g. master + nested rows + nested due-dates), the @ViewChild(DataSourceComponent) by-type pattern matches only the first data-source in template top-down order. For the others you need a template reference variable + @ViewChild('refName'):

Snippet 6HTML
<!-- TEMPLATE -->
<wuic-data-source #righeDs   [hardcodedRoute]="'fatture_inviate_righe'" [parentRecord]="record"></wuic-data-source>
<wuic-data-source #scadenzeDs [hardcodedRoute]="'scadenze'"             [parentRecord]="record"></wuic-data-source>
Snippet 7ts
// COMPONENT
import { DataSourceComponent } from 'wuic-framework-lib';

// First data-source (matched by type) -> no template ref needed
@ViewChild(DataSourceComponent) righeDs?: DataSourceComponent;

// Second data-source -> needs `#scadenzeDs` in the template + by-name ViewChild

Antipattern: document.querySelectorAll('wuic-data-source') + window.ng.getComponent(el) to filter by hardcodedRoute. Works but is fragile, depends on the window.ng debug API (not guaranteed in production). Always use template refs.