TypeScript Elements in TWV
TWV lets you build dynamic user interfaces by defining elements as TypeScript classes. Each element is a reusable building block that controls its own rendering and behavior. The runtime takes care of instantiating, rendering, and updating these elements for you.
How Elements Work
Section titled “How Elements Work”- Definition: You define an element as a TypeScript class that extends the
ELEMENTorCONTAINER_ELEMENTabstract class. - Discovery: When a
.twvfile is loaded, the runtime finds each element and creates an instance of its class. - Rendering: The runtime calls the
rendermethod on each instance, passing in arguments from the.twvfile. - DOM Integration: The element’s
rootDOM node is appended to its parent in the UI tree. Class names (including the TypeScript class name and any custom class from the.twvfile) are automatically added to the root for styling. - Lifecycle: The runtime continues to call
renderfor every element in a cyclic fashion, allowing elements to update in response to data or user actions. TheHMI_RUNTIME.isRenderedflag lets you check if the element is being rendered for the first time or is being updated.
The Base Class: ELEMENT
Section titled “The Base Class: ELEMENT”Every element that does not contain child elements must extend the ELEMENT class. This class defines the structure and contract for all elements, ensuring they have a root DOM node and a render method.
export abstract class ELEMENT { abstract readonly root: HTMLElement; abstract render(...args: (ARG | undefined)[]): void;}root: The main DOM node for your element. This is what gets appended to the parent in the UI tree.render: Called by the runtime to update your element. All arguments from the.twvfile are passed here.
The Base Class: CONTAINER_ELEMENT
Section titled “The Base Class: CONTAINER_ELEMENT”Every element that should contain child elements must extend the CONTAINER_ELEMENT class. This class defines the structure and contract for all container elements, ensuring they have a root DOM node, a render method, and a content property for child elements.
export abstract class CONTAINER_ELEMENT { abstract readonly root: HTMLElement; abstract readonly content: HTMLElement; abstract render(...args: (ARG | undefined)[]): void;}root: The main DOM node for your element. This is what gets appended to the parent in the UI tree.content: The DOM node that will contain the child elements. This is where child elements are appended.render: Called by the runtime to update your element. All arguments from the.twvfile are passed here.
Writing Your Own Element
Section titled “Writing Your Own Element”Here’s a step-by-step guide to creating a custom element:
- Create a TypeScript class that implements
RUNTIME_ELEMENT. - Define the
rootproperty as your main DOM node. - Implement the
rendermethod to update the DOM and handle logic. - Use arguments in
renderto control appearance and behavior. - Leverage
HMI_RUNTIME.isRenderedto distinguish between initial and update renders.
Example: HMI_CONTAINER
Section titled “Example: HMI_CONTAINER”export class HMI_DISPLAY_VALUE implements RUNTIME_ELEMENT { readonly p = document.createElement('p'); readonly root = this.p;
render( value: ARG_VAL_NUMERICAL, before: ARG_CONST_ARRAY_USINT | undefined, after: ARG_CONST_ARRAY_USINT | undefined, decimals: ARG_CONST_NUMERICAL | undefined, ): void { const _value = HMI_RUNTIME.get(value); const _before = HMI_RUNTIME.get(before, 'formattedString') ?? ''; const _after = HMI_RUNTIME.get(after, 'formattedString') ?? ''; const _decimals = HMI_RUNTIME.get(decimals) ?? 0;
const displayValue = +_value.toFixed(_decimals); this.p.innerHTML = `${_before}${displayValue}${_after}`; }}What’s Happening in the Example?
Section titled “What’s Happening in the Example?”- The class defines a
rootdiv. - The
rendermethod reads values from the runtime. - The content of the paragraph element is updated accordingly
- The runtime manages when and how often
renderis called.
Tips for Custom Elements
Section titled “Tips for Custom Elements”- Use the arguments in
renderto make your element flexible and reusable. - Add logic in
renderto update styles, classes, or content based on state or arguments. - Use
HMI_RUNTIME.isRenderedto separate initialization from updates if needed. - Custom class names from the
.twvfile are automatically added to your root element for easy styling.
Summary
Section titled “Summary”TWV elements are TypeScript classes that control their own rendering and logic. The runtime handles instantiation, rendering, and updates, so you can focus on building interactive, maintainable UI components. By following the base class structure and using the render method, you can create powerful custom elements for your application.