【问题标题】:Use multiple Templates in Vaadin Grid在 Vaadin Grid 中使用多个模板
【发布时间】:2021-12-01 00:22:48
【问题描述】:

我想在同一个网格中显示不同类型的对象(相同的超类型)。我希望它们在模板渲染器的帮助下呈现为卡片。假设我想为 PC 零件建立一个网上商店。 我会有一个抽象类AbstractPcPart

public abstract class AbstractPcPart {
    private Price price;
    private String name;
    private Int stockQuantity;
    // getters and setters
}

现在我想要拥有不同字段的不同部分。

public class GraphicsCard extends AbstractPcPart {
    private List<Connector> connections;
    private CoolingSystem coolingSystem;
    private int PciExpressVersion;
    private String cardModel;
    // getters and setters
}
public class Memory extends AbstractPcPart {
    private MemoryConfiguration configuration;
    private String formFactor;
    private int frequency;
    // getters and setters
}

我已经拥有的

我可以在列表中显示一个类型。这看起来像这样: grid view with memory only 此列表的代码:

@JsModule("./src/views/parts/card/memory-card.js")
public class PcPartsGrid extends Grid<AbstractPcPart> {
    public PcPartsGrid() {
        super();
        
        addColumn(MemoryCard.getTemplate()
                .withProperty("partCard", MemoryCard::create))
}

public class MemoryCard extends AbstractPcPartCard {
    AbstractPcPart pcPart;
    public MemoryCard (AbstractPcPart pcPart) {
        this.pcPart = pcPart;
    }
    public static MemoryCard create(AbstractPcPart pcPart) {
        return new MemoryCard(pcPart)
    }
    public static TemplateRenderer<AbstractPcPart> getTemplate() {
        return TemplateRenderer.of(
                "<memory-card memory-card='[[item.partCard]]'>"
                + "</memory-card>"
    }

有什么问题?

现在这很好,但是当尝试使用不同的模板渲染器构建网格时,这不起作用。 我尝试添加休闲工厂。

public class CardFactory {
    public static AbstractPcPart create(AbstractPcPart pcPart) {
        if (pcPart.getClass() == GraphicsCard.class) {
            return GraphicsCardCard.create(pcPart);
        } else if (pcPart.getClass() == Memory.class) {
            return MemoryCard.create(pcPart);
        } else {
            // different Pc Parts
        }
    }

    public static TemplateRenderer<AbstractPcPart> getTemplate(AbstractPcPart pcPart) {
        if (pcPart.getClass() == GraphicsCard.class) {
            return GraphicsCardCard.getTemplate();
        } else if (pcPart.getClass() == Memory.class)  {
            return MemoryCard.getTemplate();
        } else {
            // different Pc Parts
        }
    }
}

并更改了网格以使用此工厂。

@JsModule("./src/views/parts/card/memory-card.js")
@JsModule("./src/views/parts/card/graphics-card-card.js")
public class PcPartsGrid extends Grid<AbstractPcPart> {
    public PcPartsGrid() {
        super();
        
        addColumn(pcPart -> CardFactory.getTemplate(pcPart)
                .withProperty("partCard", CardFactory::create))
}

这没有按预期工作,它不是在我的网格中呈现不同的模板,而是向我显示对模板渲染器的引用。 template-renderer reference

如果这应该工作,我做错了什么,我需要改变什么,而不是显示参考,模板被渲染?

如果这是预期行为,有哪些可行的替代方案?

编辑: 自己搭建了一个示例项目,放到github上,供大家看看。 Example-Project

项目中的应用程序包含一个视图,用于我使用模板填充网格的每种不同方法。休闲的观点是存在的:

  • 原始视图(我一开始就是这样,只为一个版本的 pcPart 使用模板渲染器)
  • 使用 Cardfactory 查看(该工厂旨在为每种类型的 pcPart 使用不同的模板)这仅显示对对象的引用而不是模板(我认为这是因为我在 addColumn() 中使用了 lambda我从 vaadin Grid 继承的方法)
  • 使用 dom-if 元素查看(此视图使用 dom-if 元素,如 ollitietavainen 中的 this answer 中所述,遗憾的是它没有按预期工作:它显示两个模板而不是一个模板)
  • 不使用模板的视图(这只是一个使用值提供者的简单网格)
  • 使用组件渲染器的视图
  • 来自Vaadin 的示例视图也使用了组件渲染器

【问题讨论】:

    标签: java vaadin-flow vaadin-grid


    【解决方案1】:

    您可以在一定程度上使用条件模板。如果isSomething 属性为真,则&lt;dom-if if="item.isSomething"&gt; 模板会被标记。所以你可以使用类似的东西

    "<template is='dom-if' if='[[item.first]]'>first template</template>
    <template is='dom-if' if='[[item.second]]'>second template</template>
    <template is='dom-if' if='[[item.third]]'>third template</template>"
    

    如果item.first 为真,则呈现first template,依此类推。您需要向 TemplateRenderer 提供 firstsecondthird 属性,例如 .withProperty("first", item -&gt; item.isFirst() ).withProperty("second", item -&gt; item.isSecond()) 等。

    【讨论】:

    • 非常感谢您的快速回答。遗憾的是它仍然无法正常工作,我将准备一个最小的可运行示例。问题似乎来自 create 方法。在调试器模式下运行,未到达创建点的断点。
    • 这很好。您不需要创建类的新实例来设置属性。相反,您向 Grid 提供项目列表(使用 setItems 或通过 setDataProvider)。您使用 .withProperty() 为模板渲染器设置的属性是来自 bean 实例的值;通常它们是基本类型,如字符串、整数或布尔值。特别是当您使用“dom-if”时,映射到“if”属性的值应该是布尔值。
    • 抱歉@ollietavainen 需要这么长时间。我遇到了不同的问题,我的 IDE 经常崩溃,但最后我能够创建一个包含我尝试过的不同方法的项目。你的方法看起来很有希望,但它没有按预期工作。我还发现了一种使用组件渲染器的完全不同的方法。这很好用。虽然 vaadin 的专家在模板渲染器和组件渲染器之间做了一个performance comparison,但组件渲染器明显变慢了。
    • 是的,ComponentRenderer 是一种可能性,但它绝对是您需要小心的事情,因为正如您所注意到的,对于复杂的网格,性能影响会更加复杂。
    • 这些不是我的测量结果。我认为,无论如何我都在创建一个新实例(也用于模板渲染器),它不应该真正产生巨大的影响。是的,对于模板渲染器来说,创建一个新实例并不是绝对必要的,但这是我团队中其他项目的构建方式,我不想完全重新发明轮子。我现在的问题是你的 dom-if 方法做错了什么。它呈现两个模板,而不仅仅是我需要的一个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多