Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement InnerTemplatePart class #75

Merged
merged 1 commit into from
Dec 13, 2024

Conversation

seanpdoyle
Copy link
Contributor

The 3.3. Conditionals and Loops using Nested Templates section of the specification mentions special treatment of <template> elements with [directive] and [expression] attributes within <template> elements. They're to be treated as parts of their own, represented by an InnerTemplatePart interface:

 InnerTemplatePart : NodeTemplatePart {
    HTMLTemplateElement template;
    attribute DOMString directive;
}

This commit introduces that class, along with special treatment whenever collecting parts from an HTMLTemplateElement that also has a [directive] attribute.

To demonstrate their utility, this commit includes a test case that exercises a naive implementation of an if conditional. As a caveat, it's worth mentioning that the specification proposal explicitly mentions the nuance surrounding looping and conditional rendering:

this approach involves the template process callback cloning template
parts along with other nodes, or let author scripts manually specify to
which element each template part belongs. This quickly becomes an
entangled mess because now we could have multiple template parts that
refer to a single DOM location or an attribute, and we have to start
dealing with multiple template parts trying to override one another even
though there is no good use case for such a behavior.

We like the idea of supporting very basic control flow such as if and
foreach in the default template process callback but we don't think it's
a show stopper if the default template process callback didn't support
them in the initial cut.

This commit does not aim to introduce a canonical implementation for conditionals or looping, but it should enable a change like that in the future.

@seanpdoyle seanpdoyle requested a review from a team as a code owner December 13, 2024 15:20
The [3.3. Conditionals and Loops using Nested Templates][] section of
the specification mentions special treatment of `<template>` elements
with `[directive]` and `[expression]` attributes within `<template>`
elements. They're to be treated as parts of their own, represented by an
`InnerTemplatePart` interface:

```ts
 InnerTemplatePart : NodeTemplatePart {
    HTMLTemplateElement template;
    attribute DOMString directive;
}
```

This commit introduces that class, along with special treatment whenever
collecting parts from an `HTMLTemplateElement` that also has a
`[directive]` attribute.

To demonstrate their utility, this commit includes a test case that
exercises a naive implementation of an `if` conditional. As a caveat,
it's worth mentioning that the specification proposal explicitly
mentions the nuance surrounding looping and conditional rendering:

> this approach involves the template process callback cloning template
> parts along with other nodes, or let author scripts manually specify to
> which element each template part belongs. This quickly becomes an
> entangled mess because now we could have multiple template parts that
> refer to a single DOM location or an attribute, and we have to start
> dealing with multiple template parts trying to override one another even
> though there is no good use case for such a behavior.
>
> We like the idea of supporting very basic control flow such as `if` and
> `foreach` in the default template process callback but we don't think it's
> a show stopper if the default template process callback didn't support
> them in the initial cut.

This commit does not aim to introduce a canonical implementation for
conditionals or looping, but it should enable a change like that in the
future.

[3.3. Conditionals and Loops using Nested Templates]: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Template-Instantiation.md#33-conditionals-and-loops-using-nested-templates
Copy link
Member

@keithamus keithamus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👍

Comment on lines +13 to +18
if (node.hasAttribute('directive')) {
yield new InnerTemplatePart(node)
} else {
for (const part of collectParts(node.content)) {
yield part
}
Copy link
Contributor Author

@seanpdoyle seanpdoyle Dec 13, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@keithamus Should this conditional be flattened to treat all HTMLTemplateElement instances as InnerTemplatePart instances?

That way, ww could migrate the current collectParts behavior into this package's built-in processors while still enabling consumers that provide their own custom processors with an integration seam to handle <template> elements however they see fit.

I'm not entirely sure what the change would look like in the processors themselves. Maybe it'd be best to follow this change up with that exploration separately?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I agree, let's follow up separately.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the review! I've opened #76 to remove the special-casing and make InnerTemplatePart available to custom processors.

@seanpdoyle seanpdoyle requested a review from keithamus December 13, 2024 15:36
@keithamus keithamus merged commit 187af82 into github:main Dec 13, 2024
1 check passed
@seanpdoyle seanpdoyle deleted the inner-template-part branch December 13, 2024 15:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants