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
- HTML bindings — how the stamped view stays in sync with the article the command created.
- Web components — custom elements that can host their own command buttons.
- Schema definitions in HTML — where the property whose
typematches the new instance is declared.