# Frontend Options Usage Guide ## Overview The `frontend_options` attribute in Pydantic `Field` definitions supports **two formats** for providing options to frontend select/multiselect fields: 1. **Static List**: Predefined list of options 2. **String Reference**: Dynamic options fetched from the Options API ## Type System The type system is defined in `gateway/modules/shared/frontendOptionsTypes.py`: ```python from modules.shared.frontendOptionsTypes import FrontendOptions, OptionItem # FrontendOptions is Union[List[OptionItem], str] # OptionItem is Dict[str, Any] with "value" and "label" keys ``` ## Format 1: Static List Use static lists for fixed, predefined options that don't change based on user context. ### Example ```python from pydantic import Field from typing import List language: str = Field( default="en", description="Preferred language", json_schema_extra={ "frontend_type": "select", "frontend_readonly": False, "frontend_required": True, "frontend_options": [ {"value": "en", "label": {"en": "English", "fr": "Anglais"}}, {"value": "fr", "label": {"en": "Français", "fr": "Français"}}, {"value": "de", "label": {"en": "Deutsch", "fr": "Allemand"}}, ] } ) ``` ### When to Use Static Lists - Options are fixed constants (e.g., enum values) - Options don't require database queries - Options are the same for all users - Options are simple and don't change frequently ## Format 2: String Reference Use string references for dynamic options that come from the database or are context-aware. ### Example ```python from pydantic import Field from typing import List roleLabels: List[str] = Field( default_factory=list, description="List of role labels", json_schema_extra={ "frontend_type": "multiselect", "frontend_readonly": False, "frontend_required": True, "frontend_options": "user.role" # String reference } ) ``` ### When to Use String References - Options come from the database (e.g., user connections) - Options are context-aware (filtered by current user's permissions) - Options need centralized management - Options may change frequently - Options depend on user context or permissions ### Frontend Integration When the frontend encounters a string reference: 1. **Detect**: Check if `frontend_options` is a string (not a list) 2. **Fetch**: Call `GET /api/options/{optionsName}` (e.g., `/api/options/user.role`) 3. **Use**: Use the returned options for the select/multiselect field **Example Frontend Code**: ```typescript // Pseudocode if (typeof field.frontend_options === 'string') { // Dynamic options - fetch from API const options = await fetch(`/api/options/${field.frontend_options}`); return options; } else { // Static options - use directly return field.frontend_options; } ``` ## Available Option Names | Option Name | Description | Context-Aware | |-------------|-------------|---------------| | `user.role` | Standard role options (sysadmin, admin, user, viewer) | No | | `auth.authority` | Authentication authority options (local, google, msft) | No | | `connection.status` | Connection status options (active, inactive, expired, error) | No | | `user.connection` | User's connections (fetched from database) | Yes (requires currentUser) | ## Utility Functions The `frontendOptionsTypes` module provides utility functions: ```python from modules.shared.frontendOptionsTypes import ( isStringReference, isStaticList, validateFrontendOptions, getOptionsName, getStaticOptions ) # Check format if isStringReference(frontend_options): optionsName = getOptionsName(frontend_options) # Fetch from API: /api/options/{optionsName} elif isStaticList(frontend_options): options = getStaticOptions(frontend_options) # Use directly # Validate format if not validateFrontendOptions(frontend_options): raise ValueError("Invalid frontend_options format") ``` ## Validation The `validateFrontendOptions()` function ensures: 1. **String References**: Non-empty string 2. **Static Lists**: - List of dictionaries - Each dictionary has `"value"` and `"label"` keys - `"label"` is a dictionary (multilingual labels) ## Examples in Codebase ### Static List Example ```python # datamodelUam.py - Language field language: str = Field( default="en", json_schema_extra={ "frontend_options": [ {"value": "en", "label": {"en": "English", "fr": "Anglais"}}, {"value": "fr", "label": {"en": "Français", "fr": "Français"}}, ] } ) ``` ### String Reference Example ```python # datamodelUam.py - Role labels field roleLabels: List[str] = Field( default_factory=list, json_schema_extra={ "frontend_options": "user.role" # Dynamic - fetched from API } ) ``` ### Mixed Example ```python # datamodelRbac.py - AccessRule model roleLabel: str = Field( json_schema_extra={ "frontend_options": "user.role" # String reference } ) context: AccessRuleContext = Field( json_schema_extra={ "frontend_options": [ # Static list {"value": "DATA", "label": {"en": "Data", "fr": "Données"}}, {"value": "UI", "label": {"en": "UI", "fr": "Interface"}}, {"value": "RESOURCE", "label": {"en": "Resource", "fr": "Ressource"}} ] } ) ``` ## Best Practices 1. **Use Static Lists** for: - Enum values - Fixed constants - Simple options that don't change 2. **Use String References** for: - Database-driven options - Context-aware options - Options that need centralized management 3. **Always validate** frontend_options format when processing 4. **Document** which format is used and why in field descriptions 5. **Frontend**: Always check the type before using options ## Migration Guide If you have existing static lists that should become dynamic: 1. **Create Options Provider**: Add option logic to `gateway/modules/features/options/mainOptions.py` 2. **Register Option Name**: Add to `getAvailableOptionsNames()` function 3. **Update Field**: Change `frontend_options` from list to string reference 4. **Update Frontend**: Ensure frontend handles string references correctly ## See Also - `gateway/modules/shared/frontendOptionsTypes.py` - Type definitions and utilities - `gateway/modules/features/options/mainOptions.py` - Options API implementation - `gateway/modules/routes/routeOptions.py` - Options API endpoints - `wiki/appdoc/doc_security_role_based_access.md` - RBAC documentation with frontend_options examples