在 Vaadin 网格中使用多个模板

Use multiple Templates in Vaadin Grid

我想在同一个网格中显示不同类型的对象(相同的超类型)。我希望在模板渲染器的帮助下将它们渲染为卡片。假设我想为 PC 零件建立一个网上商店。 我会有一个摘要 Class 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

项目中的应用程序包含一个视图,包含我用来用模板填充网格的各种不同方法。存在以下观点:

您可以在一定程度上使用条件模板。如果 isSomething 属性 为真,则 <dom-if if="item.isSomething"> 模板会被标记。所以你可以使用像

这样的东西
"<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 -> item.isFirst() ).withProperty("second", item -> item.isSecond()) 等等。