Created
January 30, 2026 06:08
-
-
Save kerbymart/e83dae6dc38c61bc996956ad03110496 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Advanced TeaVM Flavour Implementation Patterns and Techniques | |
| ## Table of Contents | |
| * [1\. Introduction](#org1) | |
| * [2\. Advanced Component Patterns](#org2) | |
| * [2.1. Dynamic Component Composition](#org2.1) | |
| * [2.2. Type-Specific Component Rendering](#org2.2) | |
| * [2.3. Conditional Component Selection](#org2.3) | |
| * [2.4. Dynamic Component Creation with Fragments](#org2.4) | |
| * [2.5. Popup/Modal Component Pattern](#org2.5) | |
| * [2.6. Delegate Pattern for Component Communication](#org2.6) | |
| * [2.7. Component Destruction and Resource Management](#org2.7) | |
| * [3\. Entity Data Model Architecture](#org3) | |
| * [3.1. Typed Property System](#org3.1) | |
| * [3.2. JSON Persistence with @JsonPersistable](#org3.2) | |
| * [3.3. Property Hierarchy and Type Management](#org3.3) | |
| * [3.4. Dynamic Schema Management](#org3.4) | |
| * [3.5. Entity Relationship Patterns](#org3.5) | |
| * [3.6. Dynamic Property Addition to Entities](#org3.6) | |
| * [4\. Advanced UI Patterns](#org4) | |
| * [4.1. Interactive Table Components](#org4.1) | |
| * [4.2. Dynamic Property Management](#org4.2) | |
| * [4.3. Complex Form Handling](#org4.3) | |
| * [4.4. Custom JavaScript Integration](#org4.4) | |
| * [4.5. Asynchronous vs Synchronous Event Handling](#org4.5) | |
| * [4.6. Dynamic Content Injection](#org4.6) | |
| * [5\. Template and Component Architecture](#org5) | |
| * [5.1. Slot-Based Component Architecture](#org5.1) | |
| * [5.2. Supplier Pattern for Dynamic Values](#org5.2) | |
| * [5.3. Template Composition with <?use ?> Directive](#org5.3) | |
| * [6\. Component Communication Patterns](#org6) | |
| * [6.1. Mouse Event Handling Techniques](#org6.1) | |
| * [6.2. Dynamic Component Instantiation](#org6.2) | |
| * [6.3. State Management Strategies](#org6.3) | |
| * [7\. Performance Optimization Techniques](#org7) | |
| * [7.1. Lazy Initialization Patterns](#org7.1) | |
| * [7.2. Efficient Data Binding](#org7.2) | |
| * [7.3. Memory Management](#org7.3) | |
| * [7.4. Component Lifecycle Management](#org7.4) | |
| * [7.5. Proper Cleanup with destroy() Method](#org7.5) | |
| ## 1. Introduction | |
| This documentation provides comprehensive insights into advanced TeaVM Flavour implementation patterns and techniques, combining both universal best practices and specific implementation strategies. Unlike the general Flavour documentation, this guide explores real-world patterns that extend beyond basic usage, focusing on sophisticated approaches used in complex applications. | |
| The guide covers advanced component patterns, sophisticated data modeling techniques, UI interaction patterns, and performance optimization strategies that complement the standard Flavour documentation. These insights provide deeper understanding of how Flavour concepts can be implemented in sophisticated applications while maintaining best practices for maintainability and performance. | |
| ## 2. Advanced Component Patterns | |
| This section covers advanced component patterns that extend beyond the standard Flavour component usage, providing more sophisticated ways to compose and manage UI components. | |
| ### 2.1 Dynamic Component Composition | |
| Flavour applications often require sophisticated dynamic component composition patterns, particularly in data-driven interfaces like tables or grids. | |
| **Key Pattern**: Type-based component selection | |
| Applications can dynamically select different cell components based on data types: | |
| ```html | |
| <std:foreach var="property" in="entity.properties"> | |
| <std:if condition="property.type.equals('String')"> | |
| <custom:text-cell value="property"/> | |
| </std:if> | |
| <std:if condition="property.type.equals('List')"> | |
| <custom:list-cell value="property"/> | |
| </std:if> | |
| <std:if condition="property.type.equals('Boolean')"> | |
| <custom:boolean-cell value="property"/> | |
| </std:if> | |
| </std:foreach> | |
| ``` | |
| This pattern allows the same container structure to handle different data types with appropriate UI controls, providing flexibility while maintaining consistency. | |
| ### 2.2 Type-Specific Component Rendering | |
| Applications can implement a strategy pattern for rendering different property types: | |
| **String Properties**: Use text input components | |
| **Boolean Properties**: Use checkbox components | |
| **List Properties**: Use dropdown or list selection components | |
| **Other Types**: Can be extended with additional conditional blocks | |
| This approach provides: | |
| - **Consistent UI**: All properties follow the same rendering pattern | |
| - **Extensibility**: New property types can be added without breaking existing code | |
| - **Type Safety**: Each property type gets appropriate UI controls | |
| ### 2.3 Conditional Component Selection | |
| A powerful pattern used throughout sophisticated Flavour applications is conditional component selection based on runtime data: | |
| ```html | |
| <std:if condition="isSelected(item.id)"> | |
| <img src="icons/checked.svg" alt="" event:click="unselect(item.id)"> | |
| </std:if> | |
| <std:if condition="not isSelected(item.id)"> | |
| <img src="icons/unchecked.svg" alt="" event:click="select(item.id)"> | |
| </std:if> | |
| ``` | |
| This pattern allows for dynamic UI that responds to application state, showing different components based on conditions. | |
| ### 2.4 Dynamic Component Creation with Fragments | |
| Flavour allows for dynamic component creation using the Fragment pattern. This technique enables runtime creation of UI components based on data or user interactions. | |
| Example implementation: | |
| ```java | |
| public static void show(Content content, HTMLElement wrapper, ValueChangeListener<String> changeListener) { | |
| PopupComponent popup = new PopupComponent(Templates.create(content)); | |
| popup.wrapper = wrapper; | |
| popup.component = Templates.bind(popup, popup.wrapper); | |
| // ... | |
| } | |
| ``` | |
| The `Templates.create()` method creates a fragment from a content object, allowing for dynamic UI generation. This is particularly useful for modal dialogs, popups, and other contextual UI elements that need to be created on demand. | |
| ### 2.5 Popup/Modal Component Pattern | |
| Applications implement sophisticated popup systems that demonstrate how to handle complex UI interactions: | |
| ```java | |
| public class PopupComponent { | |
| private Fragment content; | |
| private Component component; | |
| private HTMLElement wrapper; | |
| private ValueChangeListener<String> changeListener; | |
| public static void show(Content content, HTMLElement wrapper, ValueChangeListener<String> changeListener) { | |
| PopupComponent popup = new PopupComponent(Templates.create(content)); | |
| popup.wrapper = wrapper; | |
| popup.component = Templates.bind(popup, popup.wrapper); | |
| content.setDelegate(new PopupDelegate() { | |
| @Override public void setValue(String value) { | |
| changeListener.changed(value); | |
| popup.close(); // Proper cleanup | |
| } | |
| @Override public void close() { | |
| popup.close(); | |
| } | |
| }); | |
| } | |
| public void close() { | |
| component.destroy(); // Ensures proper resource cleanup | |
| } | |
| } | |
| ``` | |
| This pattern combines fragments, delegates, and proper resource management to create reusable popup components. | |
| ### 2.6 Delegate Pattern for Component Communication | |
| Applications use a delegate pattern to enable communication between components without tight coupling: | |
| ```java | |
| public interface PopupDelegate { | |
| void setValue(String value); | |
| void close(); | |
| } | |
| public interface SelectionDelegate { | |
| void selectedValue(String value); | |
| void close(); | |
| } | |
| ``` | |
| Delegates allow child components to communicate with their parents or containing components without knowing the specific implementation details of the parent. This creates a clean separation of concerns and promotes reusability. | |
| ### 2.7 Component Destruction and Resource Management | |
| Proper resource management is crucial in single-page applications to prevent memory leaks: | |
| ```java | |
| public void close() { | |
| component.destroy(); // Critical for preventing memory leaks | |
| } | |
| ``` | |
| Always call `component.destroy()` when a component is no longer needed to ensure proper cleanup of event listeners and other resources. | |
| ## 3. Entity Data Model Architecture | |
| Advanced Flavour applications implement sophisticated entity data model systems that go beyond basic patterns. | |
| ### 3.1 Typed Property System | |
| **Core Architecture**: | |
| ```java | |
| @JsonPersistable | |
| public class Entity { | |
| private String entityType; | |
| private String entityId; | |
| private List<String> blobReferences; | |
| private List<String> linkReferences; | |
| private List<Property> properties; | |
| } | |
| public class Property { | |
| private String type; // "String", "Boolean", "Integer", etc. | |
| private String value; | |
| } | |
| ``` | |
| **Key Features**: | |
| - **Dynamic Typing**: Properties can have different types at runtime | |
| - **Schema Flexibility**: Entities can have different properties without schema changes | |
| - **Extensibility**: New property types can be added without breaking existing code | |
| ### 3.2 JSON Persistence with @JsonPersistable | |
| Applications use the `@JsonPersistable` annotation to enable automatic JSON serialization: | |
| ```java | |
| @JsonPersistable | |
| public class Entity { | |
| // Properties automatically serialized | |
| } | |
| ``` | |
| This annotation tells Flavour to generate the necessary code for JSON serialization/deserialization, making it easy to persist data to storage or transmit over networks. | |
| Serialization example: | |
| ```java | |
| public void save() { | |
| entities.forEach(entity -> { | |
| String serialized = JSON.serialize(entity).stringify(); | |
| // Handle serialized data | |
| }); | |
| } | |
| ``` | |
| ### 3.3 Property Hierarchy and Type Management | |
| Applications implement sophisticated property hierarchies: | |
| ``` | |
| Property (base class) | |
| ├── PrimitiveProperty (base class) | |
| │ ├── StringProperty | |
| │ ├── IntegerProperty | |
| │ ├── LongProperty | |
| │ ├── DoubleProperty | |
| │ └── BooleanProperty | |
| ├── ListProperty | |
| ├── EntityProperty | |
| └── IsProperty (interface) | |
| ``` | |
| This hierarchy allows for type-safe handling of different property types while maintaining a consistent interface: | |
| ```java | |
| public class Property { | |
| private String type; // Tracks the Java type | |
| private String value; | |
| // ... | |
| } | |
| ``` | |
| The `type` field preserves type information for proper deserialization and validation. | |
| ### 3.4 Dynamic Schema Management | |
| Components implement dynamic schema management: | |
| ```java | |
| public void addProperty(String propertyName, String propertyType) { | |
| Property newProperty = new Property(propertyType, propertyName); | |
| getProperties().add(newProperty); | |
| // Add property to all existing entities | |
| getEntities().forEach(entity -> { | |
| Property entityProperty = new Property(propertyType, propertyName); | |
| if(!entity.getProperties().contains(entityProperty)) { | |
| entity.getProperties().add(entityProperty); | |
| } | |
| }); | |
| } | |
| ``` | |
| This allows: | |
| - **Runtime Schema Evolution**: Add new properties to existing entities | |
| - **Backward Compatibility**: Existing entities automatically get new properties | |
| - **Consistent Data Structure**: All entities maintain the same property structure | |
| ### 3.5 Entity Relationship Patterns | |
| The entity model supports complex relationships: | |
| **Blob References**: `List<String> blobReferences` - References to binary data | |
| **Link References**: `List<String> linkReferences` - References to related entities | |
| **Property Collections**: `List<Property> properties` - Dynamic attributes | |
| ### 3.6 Dynamic Property Addition to Entities | |
| Applications demonstrate how to dynamically add properties to entities and ensure they're propagated to all existing entities: | |
| ```java | |
| public void addProperty() { | |
| getProperties().add(new Property(propertyType, propertyName)); | |
| getEntities().forEach(entity -> { | |
| Property entityProperty = new Property(propertyType, propertyName); | |
| if(!entity.getProperties().contains(entityProperty)) { | |
| entity.getProperties().add(entityProperty); // Add to existing entities | |
| } | |
| }); | |
| } | |
| ``` | |
| This pattern ensures data consistency when schema changes occur dynamically. | |
| ## 4. Advanced UI Patterns | |
| ### 4.1 Interactive Table Components | |
| Advanced table components implement several sophisticated UI patterns: | |
| **Dynamic Row Addition**: | |
| ```java | |
| public void addRow() { | |
| getEntities().add(new Entity(generateId(), "default", new ArrayList<>(properties))); | |
| } | |
| ``` | |
| **Property Management**: | |
| ```java | |
| public void addProperty() { | |
| // Adds property to schema and all existing entities | |
| } | |
| ``` | |
| **Data Serialization**: | |
| ```java | |
| public void save() { | |
| entities.forEach(entity -> { | |
| String serialized = JSON.serialize(entity).stringify(); | |
| // Handle serialized data | |
| }); | |
| } | |
| ``` | |
| ### 4.2 Dynamic Property Management | |
| Components show advanced form handling: | |
| ```java | |
| public void createNewItem() { | |
| // Process form input and add to collection | |
| items.add(new Item(inputValue)); | |
| } | |
| ``` | |
| **Key Features**: | |
| - **Form Validation**: Input handling with proper validation | |
| - **State Management**: Maintaining item lists | |
| - **User Feedback**: Appropriate response mechanisms | |
| ### 4.3 Complex Form Handling | |
| Templates show sophisticated form patterns: | |
| ```html | |
| <input type="text" html:value="inputValue" html:change="inputValue"> | |
| <button event:async-click="createNewItem()"> | |
| Save | |
| </button> | |
| ``` | |
| ### 4.4 Custom JavaScript Integration | |
| While Flavour provides powerful templating capabilities, sometimes custom JavaScript is needed for complex DOM manipulations: | |
| ```html | |
| <script> | |
| function toggleVisibility(elementId) { | |
| document.getElementById(elementId).classList.toggle("hidden"); | |
| document.getElementById(elementId).classList.toggle("visible"); | |
| } | |
| </script> | |
| ``` | |
| Then used in templates: | |
| ```html | |
| <div class="..." onclick="toggleVisibility('dropdown-menu')"> | |
| ``` | |
| This hybrid approach allows leveraging both Flavour's reactive capabilities and direct DOM manipulation when needed. | |
| ### 4.5 Asynchronous vs Synchronous Event Handling | |
| Applications distinguish between synchronous and asynchronous operations: | |
| ```html | |
| <!-- Synchronous event - immediate UI response --> | |
| <button event:click="save()">Save</button> | |
| <!-- Asynchronous event - for operations that may take time --> | |
| <a event:async-click="loadData()">Load Data</a> | |
| ``` | |
| Use `event:async-click` for operations that might involve network calls or heavy computation to prevent blocking the UI thread. | |
| ### 4.6 Dynamic Content Injection | |
| The popup system demonstrates how to inject dynamic content into the DOM: | |
| ```java | |
| Content content = new DynamicContent(data); | |
| Popup.show(content, wrapper, newValue -> { | |
| // Handle the new value | |
| }); | |
| ``` | |
| This pattern allows for contextual UI that adapts to the current data state. | |
| ## 5. Template and Component Architecture | |
| ### 5.1 Slot-Based Component Architecture | |
| Components extend `AbstractWidget` and use slots for proper lifecycle management: | |
| ```java | |
| public class CustomComponent extends AbstractWidget { | |
| public CustomComponent(Slot slot) { | |
| super(slot); // Proper initialization with slot | |
| } | |
| // ... | |
| } | |
| ``` | |
| The `Slot` parameter ensures the component is properly integrated into the Flavour rendering system. | |
| ### 5.2 Supplier Pattern for Dynamic Values | |
| Applications use suppliers to provide dynamic values to components: | |
| ```java | |
| public class CellComponent extends AbstractWidget { | |
| private Supplier<Property> valueSupplier; | |
| @BindAttribute(name = "value") | |
| public void setValueSupplier(Supplier<Property> valueSupplier) { | |
| this.valueSupplier = valueSupplier; | |
| } | |
| public Property getValue() { | |
| return valueSupplier.get(); // Dynamic value retrieval | |
| } | |
| } | |
| ``` | |
| This pattern allows components to receive values that may change over time or be computed on demand. | |
| ### 5.3 Template Composition with <?use ?> Directive | |
| Applications use template composition to create modular UI: | |
| ```html | |
| <!-- In main template --> | |
| <?use table:com.example.components?> | |
| <table:entities-table/> | |
| <!-- In table template --> | |
| <std:foreach var="entity" in="entities"> | |
| <?use row:com.example.components?> | |
| <row:item value="entity"/> | |
| </std:foreach> | |
| ``` | |
| This allows for clean separation of concerns and reusable components across the application. | |
| ## 6. Component Communication Patterns | |
| ### 6.1 Mouse Event Handling Techniques | |
| Applications use advanced mouse event handling: | |
| ```java | |
| public void handleSelection(MouseEvent e) { | |
| HTMLElement element = (HTMLElement) e.getTarget(); | |
| String innerText = element.getInnerText(); | |
| setSelectedValue(innerText); | |
| e.preventDefault(); | |
| } | |
| ``` | |
| **Key Techniques**: | |
| - **Event Target Access**: Getting the clicked element | |
| - **Text Extraction**: Reading inner text from DOM elements | |
| - **Event Prevention**: Using `preventDefault()` to stop propagation | |
| ### 6.2 Dynamic Component Instantiation | |
| The popup system shows advanced component instantiation: | |
| ```java | |
| public static void show(Content content, HTMLElement wrapper, ValueChangeListener<String> changeListener) { | |
| Component component = new Component(Templates.create(content)); | |
| component.wrapper = wrapper; | |
| component.instance = Templates.bind(component, component.wrapper); | |
| content.setDelegate(new ComponentDelegate() { | |
| @Override public void setValue(String value) { | |
| changeListener.changed(value); | |
| component.close(); | |
| } | |
| @Override public void close() { | |
| component.close(); | |
| } | |
| }); | |
| } | |
| ``` | |
| ### 6.3 State Management Strategies | |
| Applications use several state management patterns: | |
| **Lazy Initialization**: | |
| ```java | |
| public List<Item> getItems() { | |
| if(items == null) { | |
| items = new ArrayList<>(); | |
| } | |
| return items; | |
| } | |
| ``` | |
| **Null Safety**: | |
| ```java | |
| public List<String> getReferences() { | |
| if(references == null) { | |
| references = new ArrayList<>(); | |
| } | |
| return references; | |
| } | |
| ``` | |
| ## 7. Performance Optimization Techniques | |
| ### 7.1 Lazy Initialization Patterns | |
| Applications extensively use lazy initialization: | |
| ```java | |
| public List<Item> getItems() { | |
| if(items == null) { | |
| items = new ArrayList<>(); | |
| } | |
| return items; | |
| } | |
| ``` | |
| **Benefits**: | |
| - **Memory Efficiency**: Only allocate when needed | |
| - **Performance**: Avoid unnecessary object creation | |
| - **Resource Management**: Defer expensive operations | |
| ### 7.2 Efficient Data Binding | |
| Applications use efficient data binding patterns: | |
| **Bidirectional Binding**: | |
| ```html | |
| <input type="text" html:value="value" html:change="value"> | |
| ``` | |
| **Conditional Rendering**: | |
| ```html | |
| <std:if condition="editing"> | |
| <!-- Editable content --> | |
| </std:if> | |
| <std:if condition="not editing"> | |
| <!-- Display content --> | |
| </std:if> | |
| ``` | |
| ### 7.3 Memory Management | |
| **Null Checks**: Preventing null pointer exceptions | |
| **Collection Safety**: Safe handling of potentially null collections | |
| **Resource Cleanup**: Proper component destruction with `component.destroy()` | |
| ### 7.4 Component Lifecycle Management | |
| Components must properly manage their lifecycle to prevent memory leaks: | |
| ```java | |
| public class PopupComponent { | |
| private Component component; // Reference to be cleaned up | |
| // Component is created and bound | |
| public static void show(...) { | |
| // ... | |
| popup.component = Templates.bind(popup, popup.wrapper); | |
| } | |
| // Component must be destroyed when no longer needed | |
| public void close() { | |
| component.destroy(); // Critical cleanup step | |
| } | |
| } | |
| ``` | |
| ### 7.5 Proper Cleanup with destroy() Method | |
| Always call `destroy()` on components when they're no longer needed: | |
| ```java | |
| public void close() { | |
| component.destroy(); // Releases all resources associated with the component | |
| } | |
| ``` | |
| Failure to call `destroy()` can result in memory leaks due to retained event listeners and DOM references. | |
| ## Conclusion | |
| This documentation provides comprehensive insights into advanced TeaVM Flavour implementation patterns and techniques, combining both universal best practices and specific implementation strategies. The guide covers sophisticated approaches used in complex applications, extending beyond basic Flavour usage. | |
| The key takeaways include: | |
| - Advanced component composition patterns | |
| - Sophisticated entity data modeling | |
| - Dynamic schema management | |
| - Performance optimization techniques | |
| - Component communication patterns | |
| - Memory and resource management strategies | |
| These insights complement the general Flavour documentation by providing deeper understanding of how Flavour concepts can be implemented in sophisticated applications while maintaining best practices for maintainability and performance. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment