Declarative commands

A declarative command is a command="..." attribute on a <button> that pagelove.mjs recognizes and turns into a schema mutation — creating a new instance or deleting an existing one — without any application code.

When to reach for it

Reach for a declarative command whenever a button should add a new schema instance to a view or remove an existing one. The runtime handles the DOM update and the network call; the markup carries all the intent.

Supported commands

command= value What it does
--create-instance Creates a new instance of the schema named by the button's data-schema attribute and appends it to the target element.
--remove-instance Deletes the schema instance referenced by the button's nearest [data-for] ancestor.

Only these two values are acted on by the command handler. Any other command= value on a button inside the view is ignored.

Button attributes

Attribute Required for Purpose
command both Names the action. Must be --create-instance or --remove-instance.
data-schema --create-instance URL of the schema type to instantiate.
commandfor --create-instance (outside templates) ID of the target element the new instance is appended to.

--remove-instance takes no attributes of its own — it infers its target from the nearest [data-for] ancestor of the button.

How the button is wired

pagelove.mjs dispatches command buttons through two delivery paths:

Path Where it fires How the button is found
Native command event On the element named by commandfor The runtime attaches a command listener to every element referenced by a commandfor on a [command] button at startup.
Delegated click On the view root The runtime listens for clicks anywhere inside the view and routes any [command] button that has no commandfor attribute through the same handler.

The delegated path is what makes commands work inside <template> content, where commandfor cannot point at an element that does not yet exist.

Where the target comes from

For --create-instance:

Button location Target element
Inside a [data-for] view element The schema element whose ID matches [data-for].
Anywhere else The element referenced by commandfor (resolved by the native command event).

For --remove-instance, the target is always the schema element referenced by the nearest [data-for] ancestor. A button with no [data-for] ancestor does nothing.

Inferred itemprop on the new article

After creating the new <article>, pagelove.mjs inspects the target's itemtype. If the target has one, the runtime looks up that schema and searches its property list for a property whose type matches the new instance's type. If a match is found, the new article is given that itemprop. If nothing matches, no itemprop is set.

Optimistic behavior

Both commands update the DOM first and persist in the background.

Command DOM step Network step
--create-instance Pagelove.create(typeUrl) builds the article and target.appendChild(article) inserts it immediately. target.POST(article) runs in the background when the target supports POST. The promise is stashed as article._pendingPost so later writes can await it.
--remove-instance The schema element's etag is cleared and schemaEl.remove() detaches it immediately. DELETE() is called on the detached element if it exposes one.

Examples

Creating a new note

<main id="canvas" itemscope itemtype="https://schema.host/Board">
  <!-- existing notes -->
</main>

<button
  command="--create-instance"
  commandfor="canvas"
  data-schema="https://schema.host/StickyNote">
  Add note
</button>

Activating the button creates a StickyNote article and appends it to #canvas. If Board declares a property of type StickyNote, the new article is tagged with that itemprop automatically.

Deleting the current item from inside a template

<template itemtype="https://schema.host/StickyNote">
  <article class="sticky">
    <h1 data-bind="title" contenteditable></h1>
    <button command="--remove-instance">Delete</button>
  </article>
</template>

Each stamped view sits inside a [data-for] wrapper pointing at its backing article. Clicking the Delete button removes that article from the DOM and fires DELETE() against it.

See also