首页 > 解决方案 > 在 LitTemplate 中使用 Vaadin 的 AbstractField、AbstractCompositeField 和 Composite

问题描述

Vaadin FlowLitTemplate允许使用 ID 编写模板lit-html并将其绑定到服务器端组件。带注释的 DOM ID 及其服务器端映射的 HTML 元素都必须对齐。

AbstractField, AbstractCompositeField, 和Composite都在服务器上抽象了一个超级组件类型,同时在客户端绑定到该超级元素。从服务器端实例化它们时的结果如下所示:

class FooField extends Composite<HorizontalLayout> {
  public FooField() {
    add(new TextField());
  }
}

@Route
class ExampleView extends Div {

  public ExampleView() {
    add(new FooField());
  }
}
<div>
  <vaadin-horizontal-layout>
    <vaadin-text-field></vaadin-text-field>
  </vaadin-horizontal-layout>
</div>

尝试LitTemplate在这种情况下使用时会出现问题:

class FooField extends Composite<HorizontalLayout> {
  public FooField() {
    add(new TextField());
  }
}

@Route
@Tag("example-view")
@JsModule("./example-view.ts")
class ExampleView extends LitTemplate {

  @Id
  private FooField foo;
 
  public ExampleView() {}
}
@customElement("example-view")
export class ExampleView extends LitElement {
  render() {
    return html`
      <vaadin-horizontal-layout id="foo"></vaadin-horizontal-layout>
    `;
  }
}

结果:

<example-view>
  <#shadow-root>
    <!-- FooField's inner contents are never mapped -->
    <vaadin-horizontal-layout id="foo"><vaadin-horizontal-layout>
  </#shadow-root>
</example-view>

似乎由于 Vaadin 如何使用 映射组件LitTemplate,所有复合组件都被实例化,然后绑定到LitElementDOM 元素,而不是相反。这导致ExampleView组件看似已初始化,但映射到复合组件的 DOM 树元素处于意外状态。

“呈现”的替代方法是FooField使用@Tag("foo-field")和渲染进行注释<foo-field id="foo"></foo-field>,但在客户端失败,因为没有customElements生成定义。


解决方案似乎是所有Abstract/Composite字段必须:

  1. 绑定到客户端可解析LitTemplate(导致LitTemplate不能用作Abstract/Composite组件的直接超类型的不同问题)——这很痛苦,因为Abstract*组件提供了方便的HasValueAPI;或者
  2. 在服务器端创建并通过slots注入到客户端模板中。

关于这个问题,我已经多次浏览过文档、Vaadin 的旧论坛和 StackExchange。我可以理解为什么会出现这些问题,但我想确保这里没有完美的解决方案。

标签: vaadinlit-elementvaadin-flow

解决方案


推荐阅读