Skip to content

@gluonjs/core / src / PropertyConverter

Interface: PropertyConverter<Value> ​

Type Parameters ​

Value ​

Value = unknown

Methods ​

fromAttribute()? ​

optional fromAttribute(value, type?): Value

Converts an attribute string into the JavaScript property value.

Parameters ​

value ​

string | null

type? ​

PropertyType

Returns ​

Value


toAttribute()? ​

optional toAttribute(value, type?): string | null

Converts a reflected JavaScript property value into an attribute string.

Parameters ​

value ​

Value

type? ​

PropertyType

Returns ​

string | null

Example ​

Translate a reflected Custom Element property between attribute text and its declared runtime value:

ts
import {
  GluonElement,
  defineElement,
  exposedRef,
  getPublicInstance,
  html,
  refreshGluonElements,
  renderGluonElementForServer,
  setGluonRenderDebugHook,
  type ComponentErrorBoundary,
  type ComponentErrorInfo,
  type ComponentEventMap,
  type ComponentLifecycleCallback,
  type EventDeclaration,
  type EventDeclarations,
  type GluonElementServerRender,
  type GluonRenderCause,
  type GluonRenderDebugEvent,
  type GluonRenderDebugHook,
  type PropertyConverter,
  type PropertyDeclaration,
  type PropertyDeclarations,
  type PropertyDefinition,
  type PropertyType,
  type SlotDeclaration,
  type SlotDeclarations,
  type ValueRefTarget,
} from '@gluonjs/core';

type ProductProps = { name: string; quantity: number };
type ProductEvents = { select: { id: string } };
type ProductEventMap = ComponentEventMap<ProductEvents>;
const converter: PropertyConverter<string> = { fromAttribute: (value) => value ?? '', toAttribute: (value) => value };
const nameType: PropertyType = String;
const name: PropertyDeclaration<string> = { type: nameType, converter, required: true };
const quantity: PropertyDefinition<number> = { type: Number, default: 1, reflect: true };
const selectEvent: EventDeclaration<ProductEvents['select']> = { bubbles: true, composed: true };
const mediaSlot: SlotDeclaration = { required: false, fallback: true };
const slots = { media: mediaSlot } satisfies SlotDeclarations<'media'>;
const connected: ComponentLifecycleCallback = () => console.log('connected');
const boundary: ComponentErrorBoundary = (info) => { console.error(info.source); return true; };

class ProductCard extends GluonElement<ProductEvents> {
  static override readonly properties = { name, quantity } satisfies PropertyDeclarations<ProductProps>;
  static override readonly events = { select: selectEvent } satisfies EventDeclarations<ProductEvents>;
  static override readonly slots = slots;
  declare name: string;
  declare quantity: number;
  constructor() {
    super();
    this.expose({ select: () => this.emit('select', { id: '42' }) });
    this.onConnected(connected);
    this.onErrorCaptured((info: ComponentErrorInfo) => boundary(info));
  }
  protected render() { return html`<article>${this.name} × ${this.quantity}</article>`; }
}
defineElement('product-card', ProductCard);

const element = document.createElement('product-card') as ProductCard;
const publicTarget: ValueRefTarget<Readonly<{ select(): void }>> = { value: undefined };
const publicRef = exposedRef<{ select(): void }>(publicTarget);
if (typeof publicRef === 'function') publicRef(element);
getPublicInstance<{ select(): void }>(element)?.select();
const eventMap: Partial<ProductEventMap> = { select: new CustomEvent('select', { detail: { id: '42' } }) };
const server: GluonElementServerRender = renderGluonElementForServer(ProductCard, { name: 'Lamp' });
const hook: GluonRenderDebugHook = (event: GluonRenderDebugEvent) => {
  const cause: GluonRenderCause | undefined = event.causes[0];
  console.log(event.element.localName, event.duration, cause);
};
const restore = setGluonRenderDebugHook(hook);
refreshGluonElements();
console.log(server.tagName, server.template, eventMap, publicTarget.value);
if (typeof publicRef === 'function') publicRef(undefined);
restore();

Version-matched documentation. Examples are checked against the public package contracts.