在Vaadin Grid中使用多个模板



我想在同一个网格中显示不同类型的对象(相同的超类型)。我想把它们渲染成卡片,借助模板渲染器。假设我想为个人电脑部件建立一个网上商店。我将有一个抽象类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
}

我已经有了

我可以在列表中显示一种类型。它看起来像这样:只有内存的网格视图此列表的代码:

@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
}
}
}

并将Grid更改为使用此Factory。

@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))
}

这并没有像预期的那样工作,而是在我的网格中呈现不同的模板,它向我展示了对模板渲染器的引用。模板渲染器参考

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

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

编辑:我已经建立了一个例子项目,并把它放在github,适合所有人看。示例项目

项目中的应用程序包含用于用模板填充网格的每种不同方法的视图。出现以下视图:

  • 原始视图(这是我在开始,使用模板渲染器只有一个版本的pcPart)
  • 使用Cardfactory的视图(该工厂旨在为每种类型的pcPart使用不同的模板),这只显示对对象的引用而不是模板(我认为这是因为我在addColumn()方法中使用lambda,我从vadin Grid继承)
  • 视图使用dom-if元素(这个视图是使用dom-if元素描述在这个回答从ollitetavainen,遗憾的是它不工作的预期:它显示两个模板,而不是只有一个)
  • 未使用模板 的视图(这只是一个使用值提供程序的简单网格)
  • 使用组件渲染器的视图
  • 示例-同样使用组件渲染器的vadin视图

在一定程度上可以使用条件模板。如果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提供first,secondthird属性,如.withProperty("first", item -> item.isFirst() ).withProperty("second", item -> item.isSecond())等。

最新更新