The Pagelove class

Pagelove is the class that drives declarative HTML apps. Most pages don't construct it explicitly — the library auto-instantiates one on <main> at load time.

When to reach for it

Reach for the constructor directly when an app needs explicit lifecycle control, multiple view roots, commit hooks, a filtered subset of schema instances, or when Pagelove must be driven from application code instead of from the auto-start.

Loading the library

Import the module from wherever it is served:

<script type="module">
  import { Pagelove } from 'https://pagelove.github.io/beta-js/pagelove.mjs';
</script>

Merely loading pagelove.mjs is usually enough — the auto-start handles construction. See the JavaScript overview for the full loading story.

Auto-start

When the module finishes loading, it awaits ready and then checks the document. If the page has a <main> element and no Pagelove instance has been constructed by application code (_instanceCount === 0), the library runs:

document.pagelove = new Pagelove({ view: main });
await document.pagelove.start();

The instance is then reachable as document.pagelove. Auto-start is skipped if there is no <main>, or if any application code has already called new Pagelove(...) before the ready promise resolves.

Constructor

new Pagelove(config)

The single argument is a config object. Every option is read once at construction time.

Option Type Required Description
view Element required The visible view root. Typically <main>. All rendered instances are appended here.
filter string optional CSS selector that limits which discovered schema instances this Pagelove manages.
schema Element optional (legacy) Explicit schema root element. Direct [itemscope][itemtype][id] children are scanned. Prefer filter in new code.
beforeCommit (schemaEl, prop, value) => boolean optional Called before every write. Return false to reject the write.
afterCommit (schemaEl, prop, value) => void optional Called after every successful write.
onRender (viewEl, schemaEl) => void optional Called after a template stamp has been populated from a schema article.
onPatch ({ articleId, prop }) => void optional Called when a remote patch is applied to a schema article.
ensureSchemaEl (article, prop, value) => Element optional Overrides the default routine that locates or creates the [itemprop] element a write should target.

The most-recently-constructed instance is also assigned to window.pagelove so that PageloveComponent.create can delegate into it.

Methods

start()

await pagelove.start();

Discovers <template itemtype> definitions, awaits the ready promise, performs the first full render, and begins observing the document for changes. Idempotent — calling it on an already-started instance is a no-op. Returns a promise that resolves once observation is in place.

stop()

pagelove.stop();

Disconnects every observer and removes the change, focusout, and input listeners. Use it when tearing down a Pagelove-driven region without unloading the page.

populate(viewEl, schemaId)

pagelove.populate(dialog, 'item-abc123');

Populates the [data-bind] children of viewEl from the schema article whose id is schemaId, and sets viewEl.dataset.for so subsequent commits route back to that article. Use it for dialogs, side panels, or any element outside the main view. The original innerHTML is captured on first call and restored on every subsequent call, so the same element can host different schema articles in turn.

renderAll()

pagelove.renderAll();

Forces a full re-render of the view from the current schema. Existing rendered children of the view (those carrying [data-for]) are removed, and every discovered schema instance is re-stamped through its template. Schema articles that coexist inside the view are preserved.

create(typeUrl, values = {})

const article = pagelove.create('https://schema.host/MoodNote', { mood: 'curious' });

Builds a new <article> element for the named schema type, populated from values and from any defaults declared in the schema definition. The returned article carries itemscope, itemtype, a generated id, and an [itemprop] child for every defined property. Throws if no schema definition has been discovered for typeUrl.

flushPendingPatches()

pagelove.flushPendingPatches();

Applies every patch that was deferred because its target element was focused at the time. Pagelove defers remote patches to focused inputs to avoid clobbering in-flight edits; this method drains the queue on demand.

Properties

hasPendingPatches

Read-only boolean getter. Returns true when at least one remote patch has been deferred and is waiting to be applied. Pair with flushPendingPatches() for explicit drain control.

Module exports

Export What it is
Pagelove The class documented on this page.
ReactiveTemplate Backward-compat alias for Pagelove. New code should import Pagelove.
PageloveComponent Base class for Web Components, re-exported from pagelove/component.mjs.
Draggable Drag-and-drop mixin, re-exported from pagelove/component.mjs.
registerComponentMixin Mixin registration helper, re-exported from pagelove/component.mjs.
ready Promise that resolves when the initial OPTIONS discovery completes. Awaited by start() and by the auto-start.

Examples

Explicit instantiation

<main></main>
<aside id="inbox"></aside>

<script type="module">
  import { Pagelove } from 'https://pagelove.github.io/beta-js/pagelove.mjs';

  const pagelove = new Pagelove({
    view: document.querySelector('#inbox'),
    filter: '[data-folder="inbox"]',
  });

  await pagelove.start();
</script>

A second view root is mounted on #inbox, restricted to schema instances tagged with data-folder="inbox". The default auto-start is suppressed because the application constructed an instance before ready resolved.

Intercepting writes with beforeCommit

const pagelove = new Pagelove({
  view: document.querySelector('main'),
  beforeCommit(schemaEl, prop, value) {
    if (prop === 'title' && value.trim() === '') {
      return false; // reject empty titles
    }
    return true;
  },
  afterCommit(schemaEl, prop, value) {
    console.log('committed', schemaEl.id, prop, value);
  },
});

await pagelove.start();

beforeCommit runs against every prospective write. Returning false cancels the commit; returning anything truthy lets it proceed and triggers afterCommit once the write succeeds.

See also