6.5 KiB
Related Lists and Lookup Fields Implementation
This document describes the implementation of related lists and improved relationship field handling in the application.
Features Implemented
1. Related Lists Component (/frontend/components/RelatedList.vue)
A reusable component that displays related records for a parent entity in a table format.
Features:
- Displays related records in a formatted table
- Shows configurable fields for each related record
- Supports navigation to related record detail pages
- Allows creating new related records
- Handles loading and error states
- Empty state with call-to-action button
- Automatically fetches related records or uses provided data
Usage Example:
<RelatedList
:config="{
title: 'Domains',
relationName: 'domains',
objectApiName: 'domains',
fields: [...],
canCreate: true
}"
:parent-id="tenantId"
:related-records="tenant.domains"
@navigate="handleNavigate"
@create="handleCreate"
/>
2. Lookup Field Component (/frontend/components/fields/LookupField.vue)
A searchable dropdown component for selecting related records (belongs-to relationships).
Features:
- Searchable combobox for finding records
- Fetches available records from API
- Displays meaningful field names instead of UUIDs
- Clear button to remove selection
- Configurable relation object and display field
- Loading states
Usage:
<LookupField
:field="{
type: FieldType.BELONGS_TO,
relationObject: 'tenants',
relationDisplayField: 'name',
...
}"
v-model="domainData.tenantId"
base-url="/api/central"
/>
3. Enhanced Field Renderer (/frontend/components/fields/FieldRenderer.vue)
Updated to handle relationship fields intelligently.
New Features:
- Detects BELONGS_TO field type
- Fetches related record for display in detail/list views
- Shows meaningful name instead of UUID
- Uses LookupField component for editing
- Automatic loading of related record data
Behavior:
- Detail/List View: Fetches and displays related record name
- Edit View: Renders LookupField for selection
- Falls back to UUID if related record can't be fetched
4. Enhanced Detail View (/frontend/components/views/DetailView.vue)
Added support for displaying related lists below the main record details.
New Features:
relatedListsconfiguration support- Emits
navigateandcreateRelatedevents - Passes related records data to RelatedList components
- Automatically displays all configured related lists
5. Type Definitions (/frontend/types/field-types.ts)
Added new types for related list configuration:
export interface RelatedListConfig {
title: string;
relationName: string; // Property name on parent object
objectApiName: string; // API endpoint name
fields: FieldConfig[]; // Fields to display in list
canCreate?: boolean;
createRoute?: string;
}
export interface DetailViewConfig extends ViewConfig {
mode: ViewMode.DETAIL;
sections?: FieldSection[];
actions?: ViewAction[];
relatedLists?: RelatedListConfig[]; // NEW
}
6. Backend Support (/backend/src/tenant/central-admin.controller.ts)
Added filtering support for fetching related records.
Enhancement:
@Get('domains')
async getDomains(
@Req() req: any,
@Query('parentId') parentId?: string,
@Query('tenantId') tenantId?: string,
) {
// ...
if (parentId || tenantId) {
query = query.where('tenantId', parentId || tenantId);
}
return query;
}
7. Central Entities Configuration (/frontend/composables/useCentralEntities.ts)
Added related list configurations to tenant detail view:
export const tenantDetailConfig: DetailViewConfig = {
// ... existing config
relatedLists: [
{
title: 'Domains',
relationName: 'domains',
objectApiName: 'domains',
fields: [
{ id: 'domain', apiName: 'domain', label: 'Domain', type: FieldType.TEXT },
{ id: 'isPrimary', apiName: 'isPrimary', label: 'Primary', type: FieldType.BOOLEAN },
{ id: 'createdAt', apiName: 'createdAt', label: 'Created', type: FieldType.DATETIME },
],
canCreate: true,
},
],
}
Updated domain field configuration to use lookup:
{
id: 'tenantId',
apiName: 'tenantId',
label: 'Tenant',
type: FieldType.BELONGS_TO, // Changed from TEXT
relationObject: 'tenants',
relationDisplayField: 'name',
// ...
}
User Experience Improvements
Before:
- Relationship Fields: Displayed raw UUIDs everywhere
- Editing Relationships: Had to manually enter or paste UUIDs
- Related Records: No way to see child records from parent detail page
- Navigation: Had to manually navigate to related record lists
After:
- Relationship Fields: Show meaningful names (e.g., "Acme Corp" instead of "abc-123-def")
- Editing Relationships: Searchable dropdown with all available options
- Related Records: Automatically displayed in related lists on detail pages
- Navigation: One-click navigation to related records; create button with parent context pre-filled
Example: Tenant Detail View
When viewing a tenant, users now see:
- Main tenant information (name, slug, status, database config)
- Related Lists section below main details:
- Domains list showing all domains for this tenant
- Each domain row displays: domain name, isPrimary flag, created date
- "New" button to create domain with tenantId pre-filled
- Click any domain to navigate to its detail page
Example: Creating a Domain
When creating/editing a domain:
- Tenant field shows a searchable dropdown instead of text input
- Type to search available tenants by name
- Select from list - shows "Acme Corp" not "uuid-123"
- Selected tenant's name is displayed
- Can clear selection with X button
Technical Notes
- All API calls use the centralized
$apihelper fromuseNuxtApp() - Type casting via
unknownto handle NuxtApp type issues - Filter functions use TypeScript type predicates for proper type narrowing
- Related records can be passed in (if already fetched with parent) or fetched separately
- Backend supports both
parentIdand specific relationship field names (e.g.,tenantId)
Future Enhancements
Potential additions:
- Inline editing within related lists
- Pagination for large related lists
- Sorting and filtering within related lists
- Bulk operations on related records
- Many-to-many relationship support
- Has-many relationship support with junction tables