lit / lit-element

LEGACY REPO. This repository is for maintenance of the legacy LitElement library. The LitElement base class is now part of the Lit library, which is developed in the lit monorepo.
https://lit-element.polymer-project.org
BSD 3-Clause "New" or "Revised" License
4.49k stars 318 forks source link

Render user defined template #1125

Closed LukeTOBrien closed 3 years ago

LukeTOBrien commented 3 years ago

Hello chaps,

I just wondered if it is currently possible to render user defined template?
An example of what I mean is I am creating a custom select component and a want the user to be able to define in markup the template for each item:
(Note <template> element)

<custom-select>
  <template>
     <strong>${item.name}</strong> is ${item.age} years old!
  </template>
</custom-select>

And in my component something simulair to:

render() {
  return html`<ul>
    <li>${
      this.data.map(item => template(item));
    }</li></ul>`
}

I'm not sure if this is possible, I may have a rethink of how to design....

kevinpschaaf commented 3 years ago

Because we don't yet have a good interoperable way to define templates with data interpolation in the platform, it's not yet possible to define a custom element that accepts a generic <template> that will be cloned AND bound to data by the custom element (see the Template Instantiation proposal for ideas being discussed for filling this gap in the platform).

For now we have to resort to having custom elements accept a "templating-library-specific" template as part of its API.

So for example, it is easy to define a LitElement which accepts a property that expects a Lit TemplateResult or even a function that returns a TemplateResult bound to instance-specific data. In practice this would look something like this:

@customElement('custom-select')
class CustomSelect extends LitElement {
  @property()
  data: Items[] | undefined = undefined;
  @property()
  template: (item: Item) => TemplateResult | undefined = undefined;
  render() {
    return html`
      <ul>
        <li>${this.data.map(item => this.template(item))}</li>
      </ul>
    `;
  }
}
const template = (item) => html`<strong>${item.name}</strong> is ${item.age} years old!`;
html`<custom-select .template=${template}></custom-select>`

We do have some ideas about defining a protocol of sorts for a template-library-agnostic function signature to pass these sort of templates to custom elements, such that the template library used by the user is abstracted from the library used inside the custom element, so maybe follow this issue for advancements on that idea: https://github.com/Polymer/lit-html/issues/1478

LukeTOBrien commented 3 years ago

I see. Thanks for replying, I shall indeed follow those posts you mentioned.

On Thu, Dec 17, 2020 at 9:05 PM Kevin Schaaf notifications@github.com wrote:

Because we don't yet have a good interoperable way to define templates with data interpolation in the platform, it's not yet possible to define a custom element that accepts a generic