Open annevk opened 5 years ago
Sorry for the delay in replying to this…
The basic issue is that most components need some way to reliably reference elements (parts) in their shadow tree to manipulate their contents, apply styles, or wire up event handlers.
All of the Elix components have those needs, but since you asked for specific examples, here’s a representative one. The CalendarMonth component is made up of subelements that render different parts of the calendar: the month/year, the column headers for the week days, and an CalendarDays element that can show the actual grid of dates:
<calendar-month>
<calendar-month-year-header id=“monthYearHeader"></calendar-month-year-header>
<calendar-day-names-header id=“dayNamesHeader”></calendar-day-names-header>
<calendar-days id=“daysGrid”></calendar-days>
</calendar-month>
If you set the date
property on the outer CalendarMonth, one of the things it will do in response is pass that date to the inner CalendarDays date grid. So somewhere in the definition for CalendarMonth there’s code that effectively does:
// The date has changed, pass it to the shadow element showing the grid of dates.
this.daysGrid.date = this.date;
The issue lies in the above reference to the subelement, this.daysGrid
. What’s the best way for a component to create and hold onto such references? There are currently two basic strategies:
this.shadowRoot.getElementById
. This is what we do in Elix. –or–this.$.foo
pointed to a shadow element with ID “foo". This requires a post-clone shadow tree walk via something like this.shadowRoot.querySelectorAll(‘[id]’)
. I think lit-html does something similar, although instead of using IDs, it appears to maintain a simple array. That array maps one-to-one between the ${...}
template literal placeholders and the shadow nodes produced for those placeholders.When template instantiation was proposed, the Polymer/lit-html team and I observed it would be useful to provide a cloneWithParts
template primitive that let someone clone a template and get references to the cloned parts. The developer could imperatively create a list of parts that referenced nodes in a template. (That might entail a tree walk of the template — but the walk is only being done once for the template, not once per component instance.) After invoking cloneWithParts
, the parts would now reference the nodes in the cloned shadow tree.
Given this, I think the answer to the question about what information would the part need to carry that the browser would clone is: the part would essentially be the AttributeTemplatePart
or NodeTemplatePart
from Apple’s proposal — i.e., just the information to effectively address the attribute portion or node, respectively, after the template has been cloned. The main difference from Apple’s proposal is that it’d be possible to construct a set of parts imperatively without requiring, among other things, the use of any particular mustache syntax.
@justinfagnani The above is based on my recollection of the conversation at the April 2019 F2F. If I’ve gotten anything wrong or omitted important details, please chime in.
During the F2F @JanMiksovsky and @justinfagnani brought up some use cases for being able to create your own parts, that the browser would still be responsible for to clone. E.g., having a way to deal with JavaScript properties.
It'd be interesting to know the exact use cases and requirements around this. What kind of information does such a part need to carry that the browser would be responsible to clone? Can we avoid cloning requiring executing JavaScript? Etc.
(Not saying we need this feature for v0 by the way, but it's good to know where folks want to take it as it might influence the design.)