vaadin / vaadin-core

Home Page:https://vaadin.com/docs/latest/ds/overview

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Add support for native <template> as an alternative to renderer

Haprog opened this issue · comments

Currently this would be a very nice enhancement to the following components:

  • vaadin-dialog
  • vaadin-notification
  • vaadin-overlay
  • vaadin-select

This would be a new feature (new minor version) and should be pretty simple to implement.

And maybe it could be useful also for these, but in these it would not be as useful atm.

  • vaadin-context-menu
    • Could be helpful for simple use cases even though there is already items API. Click actions would need to be set in JS anyway or via onclick="" attributes in template)
  • vaadin-grid
    • Could be useful for header and footer templates, but maybe not for main column template or row details without custom data binding.

It would be good to have this supported consistently for all cases where we currently support <template> with Polymer bindings (e.g. all grid renderers too) but for that to make sense we would also need to add some data binding implementation that would not be dependent on Polymer (to keep it working when we move on from Polymer).

Some context

Here's a PR to vaadin-select for simplifying the demos to benefit from this kind of approach: vaadin/vaadin-select#203

These demos would become even simpler and have less JS if this feature was implemented.

E.g. this kind of demo:

<vaadin-select></vaadin-select>
<template id="selectTemplate" preserve-content>
  <vaadin-list-box>
    <vaadin-item>Jose</vaadin-item>
    <vaadin-item>Manolo</vaadin-item>
    <vaadin-item>Pedro</vaadin-item>
  </vaadin-list-box>
</template>
<script>
  customElements.whenDefined('vaadin-select').then(function() {
    const template = document.getElementById('selectTemplate');
    document.querySelector('vaadin-select').renderer = function(root) {
      if (!root.firstChild) {
        root.appendChild(template.content.cloneNode(true));
      }
    };
  });
</script>

Cound then be implemented simply as something like this:

<vaadin-select>
  <template native preserve-content>
    <vaadin-list-box>
      <vaadin-item>Jose</vaadin-item>
      <vaadin-item>Manolo</vaadin-item>
      <vaadin-item>Pedro</vaadin-item>
    </vaadin-list-box>
  </template>
</vaadin-select>

Where native would be a new custom attribute that we would check for (if not present, it would be parsed as a Polymer template like it works now). Once we drop support for Polymer we could remove the native and preserve-content attributes from here.

vaadin-dialog, vaadin-select and vaadin-context-menu already just pass the <template> element over to vaadin-overlay, so implementing this in vaadin-overlay should automatically provide the functionality for vaadin-dialog, vaadin-select and vaadin-context-menu too.

Separate implementation is needed for vaadin-notification.

Sounds like a low-hanging fruit then 👍 Marker for the template could be something more descriptive like <template overlay-content> (or <template class="overlay-content"> if we still want to align with <vaadin-grid>'s <template class="header"> etc)

I kind of like <template class="overlay-content"> as it's more clear that the class is custom and not a native thing, but then its semantics is kind of similar to slot="" as it's saying where it goes (kind of a "target") and it might be confusing why this class then needs to be left out then when you want to use a Polymer template. When using a Polymer template it's also the "overlay content".

vaadin-grid-column has:

  • <template class="header">
  • <template>
  • <template class="footer">

which kind of mimics default slot and two named slots. In this case for overlay content there can only be one template so it should be the default one and there shouldn't be a need to define the "target" for it. Instead for this issue we want to differentiate between Polymer template and "native" template without Polymer processing.

For the API it would be nicer to have the extra attribute for the Polymer template instead, but that's no good for backwards compatibility.

Maybe data-static would be a better attribute name?

As a first time user I wouldn't understand what data-static means. data also gives a wrong impression since the template API would specifically be about static content.

When using a Polymer template it's also the "overlay content"

Yes the two template syntaxes are very similar, both are also "native" <template>s.

After taking a second look, I think we don't need to do anything right now :) The ideal syntax (without any markers on the <template>) already works. Using Polymer syntax for data-binding on top of that is optional and happens to work (for now) but we don't need to promote that anymore = prefer renderers in demos that need dynamic overlay content.

Once we no longer build on Polymer, we can change the internal implementation to use a renderer that reads from the <template> in case we want to retain that API.

So you're saying it's ok to promote use of <template>...</template> in demos now (for simple cases where a renderer would have worse DX and more boilerplate), even though it's currently implemented as a Polymer template, as long as we don't use the Polymer template features like data-binding in those demos?

I agree and that's kind of what I was going for initially, but I understood we don't want to do that because of Polymer.

Then I'd like to edit the above mentioned vaadin-select PR to embrace template in demos like:

<vaadin-select>
  <template>
    <vaadin-list-box>
      <vaadin-item>Jose</vaadin-item>
      <vaadin-item>Manolo</vaadin-item>
      <vaadin-item>Pedro</vaadin-item>
    </vaadin-list-box>
  </template>
</vaadin-select>

But what about the one "actual Polymer template" demo then? Should we just not mention anything about Polymer then or can we mention that using Polymer data binding works now but maybe say it's "deprecated" in favour of renderers when you need dynamic content?

And then maybe have a renderer example that actually has some dynamic part in it.

Can we also mention in the API docs (where we now talk about Polymer template support) that using Polymer features in templates is deprecated)? That would clarify the situation a bit. But we would still have nice template API for simple static content cases.

Closing this issue as we concluded that the API doesn't need to be changed now, but we can update demos to be simpler in some cases.

Above mentioned PR for vaadin-select to improve the demos was updated and merged. We may do similar demo updates to other components.