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.