Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 62 additions & 11 deletions patching-explainer.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ The processing instructions and everything between them is replaced, so the resu
</section>
```

The `<?end>` processing instruction is optional. If it is not present, the template is assumed to end at the end of the current element.

To insert at a single point, a single `<?marker>` is used:

```html
Expand All @@ -66,13 +68,13 @@ To support multiple ranges, processing instructions can be named. Any number of

```html
<div marker="results">
<?start name="part-one">
Placeholder content
<?end>
<hr>
<?start name="part-two">
Placeholder content
<?end>
<?start name="part-one">
Placeholder content
<?end>
<hr>
<?start name="part-two">
Placeholder content
<?end>
</div>

<template for="results#part-one">
Expand All @@ -84,13 +86,15 @@ To support multiple ranges, processing instructions can be named. Any number of
</template>
```

`<?end>` processing instructions can optionally include a `name` attribute. If the `name` attribute is present, it must match the `name` attribute of the corresponding `<?start>` processing instruction. If the `name` attribute is not present, it is assumed to match any open `<?start>` processing instruction(s) within this element. See also [Nested Patching](#nested-patching) for more considerations here with nested ranges.

Multiple `<?marker>` elements without place-holder content is also supported in a similar manner:

```html
<div marker="results">
<?marker name="part-one">
<hr>
<?marker name="part-two">
<?marker name="part-one">
<hr>
<?marker name="part-two">
</div>

<template for="results#part-one">
Expand All @@ -105,7 +109,6 @@ Multiple `<?marker>` elements without place-holder content is also supported in
A few details about patching:

- Templates with a valid `for` attribute are not attached to the DOM, while templates that don't apply are attached to signal an error.
- `<?end>` does not have a `name` attribute. A `<?start>` processing instruction would match the next `<?end>` sibling.
- If the patching element is not a direct child of `<body>`, the target element has to have a common ancestor with the patching element's parent.
- The patch template has to be in the same tree (shadow) scope as the target element.
- When the template's target is discovered, the content between the markers is removed, but the markers are left in the tree until the template is closed.
Expand Down Expand Up @@ -146,6 +149,54 @@ In this example, the search results populate in three steps while the product ca
</template>
```

### Nested patching

Since processing instructions are flat in the DOM, they are not nested like actual DOM elements. To support nested markers within the same direct element you should explicitly provide an `<?end>` with a `name` to faciliate matching and avoid unexpected results.

For example, to support named processing instructions for "all results" in the previous example and also specific numbered results, you should provide `<?end>` with a `name` that matches its `<?start>` processing instruction:

```html
<div marker="results">
<?start name="all-results">
<?start name="part-one">
Placeholder content
<?end name="part-one">
<hr>
<?start name="part-two">
Placeholder content
<?end name="part-two">
<?end name="all-results">
</div>
```

In the previous example if `name` attributes were not provided on the `<?end>` processing instructions, the browser would have to track which `<?start>` the `<?end>` was closing by implementing a virtual nesting (or stack) of processing instructions. That would be complex and error prone and so is not supported.

Instead, if `name` attributes were not provided, what would actually happen is that the first `<?end>` would close both the `<?start name="all-results">` and `<?start name="part-one">` processing instructions and the final `<?end>` would be ignored, which would lead to unexpected results. This is why the `name` attribute is recommended on `<?end>` processing instructions when nesting is desired.

A perhaps cleaner alternative, if you prefer not to use `name` attributes on the `<?end>` processing instructions, is to provide nesting with actual DOM elements such as `<div>`s and separate markers:

```html
<div marker="results">
<?start>
<div marker="part-one">
<?start>
Placeholder content
<?end>
</div>
<hr>
<div marker="part-two">
<?start>
Placeholder content
<?end>
</div>
<?end>
</div>
```

Since there is no nesting within the same element here, the `name` attributes are not required on either the `<?start>` or `<?end>` processing instructions and the intention is clear. However, you may still provide them if you wish.

Both of these options (use of `name` attributes, or use of DOM elements to provide the nesting structure) are supported for nesting.

## Marker APIs

The new `<?marker>`, `<?start>`, and `<?end>` nodes would be represented with the `ProcessingInstruction` interface. That interface would receive `getAttribute`, `setAttribute` methods etc. See https://github.com/whatwg/dom/pull/1454.
Expand Down