Skip to content

Templates and Metadata

A template defines the form, and an instance holds its values. The CEE accepts both as parsed JavaScript objects and exposes the current instance as JSON-LD or YAML.

Supply a Template

Assign the template after configuring the element:

cee.templateObject = template;

This assignment builds the form. The property accepts one successful assignment; to show another template, create a new CEE element.

Supply an Existing Instance

When the template and instance are available together, use the combined input:

cee.templateAndInstanceObject = {
  templateObject: template,
  instanceObject: instance,
};

The CEE can then build the populated form once. The instance must have been created from the supplied template.

Separate properties are available when the values arrive at different times:

cee.instanceObject = instance;
cee.templateObject = template;

Either order works; the CEE waits for a template before rendering. Each property still accepts only one successful assignment. Do not combine templateAndInstanceObject with either separate property.

A duplicate assignment is ignored and reported through the console and eventHandler:

CEE ERROR: CEDAR Embeddable Editor: "instanceObject" ignored, because the instance is already set.
Each input takes one assignment; create a new editor element to load a different artifact.

If the CEE cannot parse a combined input, it renders nothing and leaves both properties available for a corrected assignment. An unreadable instanceObject similarly does not consume that input.

JSON Schema and YAML Templates

The CEE accepts templates in CEDAR's JSON Schema and YAML representations. Assign the parsed object in either case:

cee.templateObject = template;

Browsers parse JSON natively but need a library such as js-yaml to parse YAML source text. Both representations pass through the same CEDAR model library and produce the same form.

Read the Current Instance

The output properties are read-only and have no side effects:

Property Value
currentMetadata The current instance as a CEDAR JSON-LD object.
currentMetadataYaml The current instance as a CEDAR YAML string.
const instance = cee.currentMetadata;
const yaml = cee.currentMetadataYaml;

Existing instances are supplied as JSON-LD, regardless of the template's input representation.

Observe Changes

The CEE dispatches a bubbling change event across the shadow boundary whenever an operation changes the serialized instance. It does not dispatch for focus, blur, page navigation, read-only activity, or a write that leaves the instance unchanged.

The package declares the event as CustomEvent<CeeChangeDetail>:

import type { CeeChangeDetail } from 'cedar-embeddable-editor';

const cee = document.querySelector('cedar-embeddable-editor');
if (!cee) throw new Error('CEE element is missing');

cee.addEventListener('change', (event) => {
  const detail: CeeChangeDetail = event.detail;
  console.log(detail.operation, detail.path, detail.value);
  saveButton.disabled = !detail.validity;
});

Each event detail contains the state after the operation:

Member Meaning
operation valueChanged, multiInstanceAdded, multiInstanceCopied, or multiInstanceDeleted.
path Component path from the template root.
value Value supplied to the model operation.
validity Whether the resulting instance is valid.
dataQualityReport Full validation report for the resulting instance.
title, description Current instance envelope values, or null.

Repeating-group events also include the legacy detail.message value multiInstanceAdded, multiInstanceCopied, or multiInstanceDeleted.

Angular can receive the same event with (change)="onChange($event)".

Loading a canonical instance does not produce a change event. The exception is a temporal value with more precision than the template permits: the CEE normalizes the value during loading and reports that change. Attach the listener before assigning the artifact if the application needs to observe it.

Track Unsaved Changes

The CEE does not maintain a dirty flag. Store a structural snapshot of currentMetadata after loading and after each successful save, then compare it with the current value after every change. This also clears the dirty state when a user exactly reverses an edit.

Autosave works the same way: read the current instance on the application's schedule and send it to the application's own service.

const SAVE_INTERVAL = 15000;

setInterval(async () => {
  await fetch('/api/metadata/draft', {
    method: 'POST',
    headers: { 'Content-Type': 'application/yaml' },
    body: cee.currentMetadataYaml,
  });
}, SAVE_INTERVAL);

Temporal Values

A temporal field's temporalType, temporalGranularity, and timezoneEnabled settings determine the stored lexical value. The CEE fills omitted lower-order parts with their minimum valid value:

Declared precision Stored value
Date, year 2026-01-01
Date, month 2026-08-01
Date, day 2026-08-09
Time, hour 21:00:00
Time, minute 21:45:00
Time, second 21:45:32
Time, decimal second 21:45:32.001
Date-time, day 2026-08-09T00:00:00
Date-time, minute 2026-08-09T21:45:00

When time zones are enabled, the CEE appends Z or the selected +/-HH:mm offset. When they are disabled, it removes any offset.

The template's granularity also governs loaded values. For example, a day-level date-time field normalizes 2026-08-09T21:45:32.125-07:00 to 2026-08-09T00:00:00-07:00 rather than retaining invisible precision.