wiki/b-reference/frontend-nyla/formgenerator.md
ValueOn AG cf2e875968 uüd
2026-04-14 00:15:28 +02:00

9.2 KiB

FormGenerator -- Referenz

Uebersicht

Der FormGenerator besteht aus mehreren Komponenten:

Komponente Datei Zweck
FormGeneratorTable components/FormGenerator/FormGeneratorTable/FormGeneratorTable.tsx Generische Datentabelle mit Pagination, Sortierung, Filterung, Suche, Selektion, Bulk-Actions
FormGeneratorControls components/FormGenerator/FormGeneratorControls/FormGeneratorControls.tsx Toolbar: Suche, Pagination, Batch-Action-Buttons, "Select All Filtered"-Banner
FormGeneratorForm components/FormGenerator/FormGeneratorForm/FormGeneratorForm.tsx Dynamische Formulare aus Backend-Attribut-Definitionen
FormGeneratorList components/FormGenerator/FormGeneratorList/FormGeneratorList.tsx Listen-Darstellung

Diese Referenz fokussiert auf FormGeneratorTable und das zugehoerige Backend-API-Pattern.


FormGeneratorTable -- Props

Datenanbindung

Prop Typ Beschreibung
data T[] Anzuzeigende Datensaetze (aktuelle Seite)
columns ColumnConfig[] Spaltendefinitionen (key, label, type, sortable, filterable, searchable, filterOptions, width)
apiEndpoint string? Backend-Endpunkt fuer automatische Filter-/ID-Abfragen
hookData { refetch, pagination, fetchFilterValues? } Daten-Hook mit Refetch-Callback und Pagination-Metadata
supportsBackendPagination boolean Aktiviert serverseitige Pagination, Sortierung und Filterung

Interaktion

Prop Typ Beschreibung
selectable boolean Aktiviert Zeilen-Selektion (Checkboxen)
onSelectionChange (selectedIds: Set<string>) => void Callback bei Aenderung der Selektion
idField string Feld fuer eindeutige ID (Default: "id")
isRowSelectable (row: T) => boolean Bestimmt, ob eine Zeile selektierbar ist
batchActions BatchAction[] Bulk-Aktionen fuer selektierte Zeilen
actionButtons ActionButton[] Zeilen-Aktionen (Edit, Delete etc.)

BatchAction Interface

interface BatchAction<T> {
  label: string;
  icon?: React.ReactNode;
  loading?: boolean;
  onClick: (selectedRows: T[]) => void | Promise<void>;
  isApplicable?: (row: T) => boolean;
}

isApplicable ermoeglicht pro Action zu bestimmen, welche der selektierten Zeilen fuer diese Aktion qualifizieren. Der Button zeigt dann (applicableCount/totalSelected) und ist disabled wenn applicableCount === 0.


Unified Filter API

Prinzip

Alle Daten-Endpunkte unterstuetzen drei Modi ueber Query-Parameter auf dem gleichen Endpunkt:

Modus Query-Parameter Response Zweck
Normal (default) pagination={...} { items: T[], pagination: PaginationMetadata } Paginierte Datenliste
filterValues mode=filterValues&column=xxx&pagination={crossFilters} string[] Distinct-Werte fuer Spaltenfilter-Dropdown
ids mode=ids&pagination={filters} string[] Alle IDs der gefilterten Datensaetze

Kein separater /filter-values-Endpunkt. Alle alten /filter-values-Sub-Pfade wurden entfernt (Stand 2026-04-13).

Cross-Filtering

Bei mode=filterValues werden alle aktiven Filter ausser dem angeforderten Column-Filter angewendet (Cross-Filtering). So zeigt z.B. der Status-Filter nur Werte an, die bei den aktuell gesetzten Mandant- und Typ-Filtern vorkommen.

Beispiele

# Normale Liste (Seite 1, 20 Eintraege)
GET /api/users/?pagination={"page":1,"pageSize":20,"sort":[{"field":"name","direction":"asc"}]}

# Filter-Werte fuer Spalte "status" (mit Cross-Filter auf mandateLabel)
GET /api/users/?mode=filterValues&column=status&pagination={"filters":{"mandateLabel":"Demo AG"}}

# Alle IDs der gefilterten Ansicht (fuer "Select All Filtered")
GET /api/users/?mode=ids&pagination={"filters":{"status":"active"},"search":"admin"}

Backend-Implementierung

Zentrale Hilfsfunktionen in gateway/modules/routes/routeHelpers.py:

Funktion Zweck
handleFilterValuesMode(db, modelClass, column, ...) SQL-basierte Distinct-Werte via DB-Connector
handleIdsMode(db, modelClass, ...) SQL-basierte ID-Liste via DB-Connector
handleFilterValuesInMemory(items, column, ...) In-Memory Distinct-Werte (fuer enriched/aggregierte Listen)
handleIdsInMemory(items, ...) In-Memory ID-Liste
parseCrossFilterPagination(column, paginationJson) Parsed Pagination-JSON und entfernt den angeforderten Column-Filter
_applyFiltersAndSort(items, paginationParams) In-Memory Filterung und Sortierung
_extractDistinctValues(items, column, ...) Distinct-Werte aus Item-Liste extrahieren
paginateInMemory(items, paginationParams) In-Memory Paginierung

Route-Integration Pattern

@router.get("/", response_model=PaginatedResponse[MyModel])
def list_items(
    request: Request,
    pagination: Optional[str] = Query(None),
    mode: Optional[str] = Query(None, description="'filterValues' or 'ids'"),
    column: Optional[str] = Query(None, description="Column key"),
    context: RequestContext = Depends(getRequestContext),
):
    if mode in ("filterValues", "ids"):
        from modules.routes.routeHelpers import handleFilterValuesInMemory, handleIdsInMemory
        items = _buildFullList(context)
        if mode == "filterValues":
            if not column:
                raise HTTPException(status_code=400, detail="column required")
            return handleFilterValuesInMemory(items, column, pagination)
        return handleIdsInMemory(items, pagination)

    # Normal paginated list...

Selektion

ID-basierte Selektion

Die Selektion arbeitet mit IDs (nicht Zeilen-Indizes). Das idField-Prop bestimmt, welches Feld als eindeutiger Schluessel verwendet wird (Default: "id").

State Typ Beschreibung
selectedIds Set<string> Menge der selektierten IDs

Selektion-Reset

Die Selektion wird automatisch zurueckgesetzt bei:

  • Seitenwechsel (currentPage)
  • Seitengroesse-Aenderung (pageSize)
  • Filter-Aenderung
  • Suchbegriff-Aenderung
  • Sortier-Aenderung

Select All Filtered

Wenn apiEndpoint und supportsBackendPagination gesetzt sind, zeigt die Toolbar einen "Alle X Eintraege auswaehlen"-Button. Dieser ruft GET {apiEndpoint}?mode=ids&pagination={currentFilters} auf und fuegt alle zurueckgegebenen IDs zur Selektion hinzu.

Ein "Auswahl aufheben"-Button erscheint, wenn "Select All Filtered" aktiv ist.

Row-Level Delete

Wenn eine Zeile geloescht wird (via actionButtons Delete), wird deren ID automatisch aus selectedIds entfernt.


FilterValuesList (Spaltenfilter-Dropdown)

Wenn ein filterbarer Spalten-Header geklickt wird, laedt das Dropdown die Distinct-Werte:

  1. column.filterOptions (statische Enum) -- wird direkt verwendet, kein Backend-Call
  2. hookData.fetchFilterValues(columnKey, crossFilters) -- falls im Hook bereitgestellt
  3. GET {apiEndpoint}?mode=filterValues&column=xxx&pagination={currentFilters} -- automatisch

Bei mehr als 10 Werten erscheint ein Suchfeld (Client-seitige Filterung der geladenen Werte).

Boolean-Spalten rendern als "Ja"/"Nein". Datum-Spalten rendern als Range-Picker.


Migrierte Endpunkte (Stand 2026-04-13)

Alle folgenden Endpunkte unterstuetzen mode=filterValues und mode=ids:

Core Routes

Route-Datei Endpunkt Methode
routeDataUsers.py GET /api/users/ SQL + In-Memory (je nach Scope)
routeDataConnections.py GET /api/connections/ In-Memory
routeDataPrompts.py GET /api/prompts/ In-Memory
routeInvitations.py GET /api/invitations/ In-Memory
routeSubscription.py GET /api/subscriptions/admin/all In-Memory
routeAdminFeatures.py GET /api/admin/features/instances In-Memory
routeAdminFeatures.py GET /api/admin/features/templates/roles In-Memory
routeAdminFeatures.py GET /api/admin/features/instances/{id}/users In-Memory
routeAdminRbacRules.py GET /api/admin/rbac/roles In-Memory
routeDataMandates.py GET /api/mandates/ SQL + In-Memory (je nach Scope)
routeDataMandates.py GET /api/mandates/{id}/users In-Memory
routeDataFiles.py GET /api/files/list SQL + In-Memory Fallback
routeWorkflowDashboard.py GET /api/automation/dashboard/ (Runs) Enriched + SQL
routeWorkflowDashboard.py GET /api/automation/dashboard/workflows Enriched + SQL
routeBilling.py GET /api/billing/view/users/transactions Billing-Interface

Feature Routes

Route-Datei Endpunkt Methode
routeFeatureTrustee.py GET /api/trustee/{id}/documents RBAC SQL + In-Memory Fallback
routeFeatureTrustee.py GET /api/trustee/{id}/positions RBAC SQL + In-Memory Fallback
routeFeatureRealEstate.py GET /api/realestate/{id}/projects In-Memory
routeFeatureRealEstate.py GET /api/realestate/{id}/parcels In-Memory