Functions
-
getUniqueId : {string}
-
For the most part, VComponents should not need to render ids on child content. However, in some cases this may be necessary. For example, in order to set up a relationship between a label and the element that the label references, the label and labeled content must rendezvous on a common id. Specifying fixed ids is problematic as this can lead to conflicts with other ids on the page. The getUniqueId() method helps solve this problem by creating producing an id that is guaranteed not to conflict with ids rendered by other components.
The id returned by getUniqueId() is typically used to provide a prefix (or suffix) for what would otherwise be a static id for some element rendered by the VComponent.
The usage model is:
- In the VComponent's constructor, check to see whether the VComponent already has a props.id value. If so, this can be used as a prefix for other ids and calling getUniqueId() is unnecessary.
- Otherwise, call getUniqueId() to retrieve the unique prefix for this component
- Store the result of the #1/#2 in an instance variable for later use.
- When rendering, use the previously stored prefix to generate unique ids for any elements that need them.
- Don't forget to include "id" in the list of ObservedGlobalProps in order to ensure that the VComponent receives the value of this global HTML attribute.
Putting this all together, we end up with a component like this:
import { h, Component, ComponentChild } from 'preact'; import { customElement, ExtendGlobalProps, ObservedGlobalProps, getUniqueId } from 'ojs/ojvcomponent'; import "ojs/ojinputtext"; import "ojs/ojlabel"; export type Props = ObservedGlobalProps<'id'>; @customElement('oj-demo-unique-id') export class DemoUniqueId extends Component<ExtendGlobalProps<Props>> { private uniquePrefix: string; constructor(props: Readonly<Props>) { super(props) this.uniquePrefix = props.id ?? getUniqueId(); } render(): ComponentChild { const inputTextId = `${this.uniquePrefix}_input`; return ( <div> <oj-label for={ inputTextId }>Label</oj-label> <oj-input-text id={ inputTextId } value="Value"/> </div> ); } }Returns:
- Type
- string
-
Root
-
Root is a Preact component that can be used to wrap the VComponent's child content. This component should only be used for cases where the VComponent needs to control how observed global properties are rendered on the component's root custom element. In all other cases the non-wrapped child content should be returned directly.
See the Root Element section for more details.
Decorators
-
customElement(tagName)
-
Class decorator for VComponent custom elements. Takes the tag name of the custom element.
Parameters:
Name Type Description tagNamestring The custom element tag name -
method
-
Method decorator for VComponent methods that should be exposed on the custom element. Non decorated VComponent methods will not be made available on the custom element.
Type Definitions
-
Action<Detail extends object = {}>
-
The Action type is used to identify properties as action callbacks. Actions are functions that the VComponent invokes when it wants to communicate some activity to the outside world. When the VComponent is being consumed as a custom element, this results in an actual DOM CustomEvent being dispatched. Alternatively, when the VComponent is referenced via its Preact Component class, the provided callback is invoked directly and no CustomEvent is produced.
Actions have an optional detail type. If specified, the detail value is either passed to the consumer via the CustomEvent detail payload for the custom element case, or directly into the callback for the Preact component case.
Note that Action properties must adhere to a specific naming convention: "on<PascalCaseEventName>". For the custom element case, the type of the CustomEvent will be derived by converting the first character of the event name to lower case. Thus, the "onGreetingComplete" property will generate a CustomEvent of type "greetingComplete".
See Actions and Events for more info.
Signature:
(detail?: Detail) => void
-
Bubbles
-
As discussed in Actions and Events, the custom events generated by Actions do not bubble by default. The Bubbles marker type can be combined with the Action type to indicate that the Action's custom events should bubble.
type Props = { // This action generates bubbling custom events onThisActionBubbles?: Action & Bubbles; // This action generates non-bubbling custom events onThisActionDoesNotBubble?: Action; } -
CancelableAction<Detail extends object = {}>
-
Some JET Web Components support an asynchronous, event-based cancelation contract where prior to performing some operation, the component dispatches a "cancelable" event. If the application cancels the event, the operation is not performed. The <oj-file-picker>'s ojBeforeSelect event is one example of such an API.
The VComponent API has built-in support for this pattern via the CancelableAction type. Like the plain old Action type, CancelableAction is a function type that is used for defining callback-centric properties. One key difference between these types is that CancelableAction returns a Promise. If the Promise resolves successfully, the action is considered to be accepted. If the Promise is rejected, the action is canceled.
As with Action-typed properties, CancelableActions exhibit different behavior depending on whether the VComponent is being consumed as a custom element or via its Preact Component class.
When consumed as a custom element, invoking a CancelableAction results in a CustomEvent being created and dispatched. The detail payload of this custom event is augmented with one extra field: an "accept" method. The accept method takes a single argument: the Promise that produces the cancelation result.
When consumed via the Preact Component class, no custom event is dispatched. Instead, the callback returns the cancelation promise directly.
Signature:
(detail?: Detail) => Promise<void>
-
DynamicSlots
-
In most cases when a Web Component accepts slot content, the number and names of the slots are known, as these are defined by the component's public API. However, in some cases components may allow an arbitrary number of slots to be specified, where the slot names are not known up front. The <oj-switcher> component is an example of a component that accepts a dynamically defined (rather than predefined) set of slots.
The VComponent API supports such cases via the DynamicSlots and DynamicTemplateSlots types. A single property can be marked with the DynamicSlots type:
type Props = { // This property will be populated with all // "unknown" slots. items?: DynamicSlots; // Other properties go here... }When the VComponent is consumed in custom element form, this property will be populated with entries for each "dynamic" slot. That is, an entry will be added for each child element with a slot attribute that does not correspond to a known Slot-typed property. The property acts as a map from slot name to Slot instance. The VComponent can use whatever heuristic it prefers to decide which (if any) slots should be included in the rendered output.
Signature:
Record<string, VComponent.Slot>
-
DynamicTemplateSlots<Data>
-
The DynamicTemplateSlots type is a companion to DynamicSlots that is used in cases where the component accepts an arbitrary number of template slots. VComponents may declare a single property of type DynamicTemplateSlots. When the component is used as a custom element, this property will be populated with one entry for each "dynamic" template slot, where the key is the slot name and the value is a TemplateSlot function.
Note that each VComponent class can only contain a single dynamic slot property. That is, each VComponent can have one property of type DynamicSlots or one property of type DynamicTemplateSlots, but not both.
Signature:
Record<string, VComponent.TemplateSlot<Data>>
-
ElementReadOnly<T>
-
By default, writeback property mutations can be driven either by the component, typically in response to some user interaction, or by the consumer of the component. In some cases, writeback properties are exclusively mutated by the component itself. Writeback properties that cannot be mutated by the consumer are known as read-only writeback properties. The <oj-input-text>'s rawValue property is an example of such a property.
Read-only writeback properties are declared in a similar manner to plain old writeback properties, with one important difference: the ElementReadOnly utility type is used as a marker to identify the that the property is read-only.
Declarations for both forms of writeback properties can be seen below:
type Props = { // This is a normal writeback property: value?: string; onValueChanged?: PropertyChanged<string> // This is a read-only writeback property: rawValue?: ElementReadOnly<string>; onRawValueChanged?: PropertyChanged<string> } Signature:
T
-
ExtendGlobalProps<Props>
-
As discussed in the Properties section, all VComponents must minimally include the GlobalProps in their property types. ExtendGlobalProps is a convenience type for combining component-specific properties with GlobalProps, e.g.:
import { customElement, ExtendGlobalProps } from 'ojs/ojvcomponent'; // These are the component-specific props: type Props = { greeting?: string; name?: string; } // Below we merge the component props with the // global props using ExtendGlobalProps @customElement('oj-hello-world-with-props') export class HelloWorld extends Component<ExtendGlobalProps<Props>> { Signature:
Readonly<Props> & ojvcomponent.GlobalProps
-
GlobalProps
-
The GlobalProps type defines the set of global properties that are supported by all VComponents. This includes three categories of properties:
The following properties are included from category 1:
- accessKey
- autocapitalize
- autofocus
- class
- contentEditable
- dir
- draggable
- enterKeyHint
- hidden
- id
- inputMode
- lang
- role
- slot
- spellcheck
- style
- tabIndex
- title
- translate
The following ARIA-specific attributes are included from category 2:
- aria-activedescendant
- aria-atomic
- aria-autocomplete
- aria-busy
- aria-checked
- aria-colcount
- aria-colindex
- aria-colspan
- aria-controls
- aria-current
- aria-describedby
- aria-details
- aria-disabled
- aria-errormessage
- aria-expanded
- aria-flowto
- aria-haspopup
- aria-hidden
- aria-invalid
- aria-keyshortcuts
- aria-label
- aria-labelledby
- aria-level
- aria-live
- aria-modal
- aria-multiline
- aria-multiselectable
- aria-orientation
- aria-owns
- aria-placeholder
- aria-posinset
- aria-pressed
- aria-readonly
- aria-relevant
- aria-required
- aria-roledescription
- aria-rowcount
- aria-rowindex
- aria-rowspan
- aria-selected
- aria-setsize
- aria-sort
- aria-valuemax
- aria-valuemin
- aria-valuenow
- aria-valuetext
The following event listener properties are included from category 3:
- onBlur
- onClick
- onContextMenu
- onDblClick
- onDrag
- onDragEnd
- onDragEnter
- onDragExit
- onDragLeave
- onDragOver
- onDragStart
- onDrop
- onFocus
- onKeyDown
- onKeyPress
- onKeyUp
- onMouseDown
- onMouseEnter
- onMouseLeave
- onMouseMove
- onMouseOut
- onMouseOver
- onMouseUp
- onPointerOver
- onPointerEnter
- onPointerDown
- onPointerMove
- onPointerUp
- onPointerCancel
- onPointerOut
- onPointerLeave
- onTouchCancel
- onTouchEnd
- onTouchMove
- onTouchStart
- onWheel
The above event listener properties can also be specified with the "Capture" suffix (e.g., "onClickCapture") to indicate that the listener should be registered as a capture listener.
Finally, onfocusin and onfocusout properties are also available, though technically speaking these are not global events.
-
ObservedGlobalProps
-
The ObservedGlobalProps type is used to identify the subset of GlobalProps that the VComponent implementation needs to observe. When a VComponent is used as a custom element, ObservedGlobalProps determines which of the GlobalProps values will be extracted from the DOM and passed into the VComponent. Properties that are selected using ObservedGlobalProps are also included in the custom element's observedAttributes list. As a result, updates to observed global properties will trigger the VComponent to render with the new values.
The ObservedGlobalProps type acts as a Pick type, where properties are implicitly picked from GlobalProps. The resulting type is typically merged with any component-specific properties via a union.
See the Observed Global Properties section for more details.
-
PropertyChanged<T>
-
The PropertyChanged type is used to identify callback properties that notify VComponent consumers of writeback property mutations. Writeback property callbacks must adhere to the naming convention of "on
Changed", where "PropertyName" is the name of the writeback property with the first character converted to upper case: type Props = { // This is a writeback property value?: string; // This is the corresponding property changed callback onValueChanged?: PropertyChanged} See the Writeback Properties section for more details.
Signature:
(value: T) => void
-
Slot
-
The Slot type identifies properties as representing named slot children. This type is an alias for Preact's ComponentChildren type. As such, the value of a slot property can either be embedded directly in a virtual DOM tree or can be passed to Preact's toChildArray.
See Children and Slots for more details.
Signature:
ComponentChildren
-
TemplateSlot<Data extends object>
-
The TemplateSlot type identifies properties as representing named template slot children. Unlike the Slot type, TemplateSlot is a functional type that takes some context and returns the slot children.
See the Template Slots section for more details.
Signature:
(data: Data) => VComponent.Slot