1

In a grid I want to display different elements. Depending on the type of the element I want to use a different TemplateRenderer. One solution to this problem would be to use dom-if elements in the template. if the «if» parameter is false, the element should not get rendered. The problem is, that in my templates all the elements get rendered, even though the debugger shows me that the method, that is responsible for determining the truth value, sometimes returns false.

every template gets rendered twice

Here is my code for the grid:

// these are the two javascript templates
@JsModule("./src/views/parts/card/graphics-card-card.js")
@JsModule("./src/views/parts/card/memory-card.js")
public class PcPartsDomIfGrid extends Grid<AbstractPcPart> {
    private static final long serialVersionUID = 7474489703766322949L;

    public PcPartsDomIfGrid() {
        super();

        initColumn();
    }

    private boolean isMemory(AbstractPcPart pcPart) {
        return pcPart.getClass().equals(Memory.class);
    }

    private boolean isGraphicsCard(AbstractPcPart pcPart) {
        return pcPart.getClass().equals(GraphicsCard.class);
    }

    private void initColumn() {
        addColumn(Objects.requireNonNull(CardFactory.getTemplate())
                .withProperty("partCard", CardFactory::create)
                .withProperty("isMemory", this::isMemory)
                .withProperty("isGraphicsCard", this::isGraphicsCard));
    }
}

Here is the Code for the Factory:

public class CardFactory {
    public static AbstractPcPartCard create(AbstractPcPart pcPart) {
        if (pcPart.getClass().equals(GraphicsCard.class)) {
            return GraphicsCardCard.create((GraphicsCard) pcPart);
        } else if (pcPart.getClass().equals(Memory.class)) {
            return MemoryCard.create((Memory) pcPart);
        } else {
            // different PC parts
            return null;
        }
    }

    public static TemplateRenderer<AbstractPcPart> getTemplate() {
        String memoryTemplate = MemoryCard.getTemplateString();
        String graphicsCardTemplate = GraphicsCardCard.getTemplateString();

        String combinedTemplate = memoryTemplate + graphicsCardTemplate;
        return TemplateRenderer.of(combinedTemplate);
    }
}

Both MemoryCard and GraphicsCardCard are similar, here is the code for MemoryCard:

public class MemoryCard extends AbstractPcPartCard {
    Memory pcPart;

    public MemoryCard(Memory pcPart) {
        this.pcPart = pcPart;
    }

    public static MemoryCard create(Memory pcPart) {
        return new MemoryCard(pcPart);
    }

    // getters

    public static String getTemplateString() {
        return "<memory-card is='dom-if' if='[[item.isMemory]]'"
                + " part-card='[[item.partCard]]'>"
                + "</memory-card>";
    }
}

The complete code can be found on github. The relevant view is located in the package:

com.example.application.ui.views.partsDomIf

Anna Koskinen
  • 1,362
  • 3
  • 22
Dario Viva
  • 215
  • 1
  • 10

1 Answers1

3

The dom-if attribute must be used on a <template> tag, such as

<template is='dom-if' if='[[item.important]]'>this is shown when the item is <b>important</b></template>
<template is='dom-if' if='[[!item.important]]'>this is shown when the item is <b>NOT important</b></template>

Note that the !property.name negation is the only logical operation available, you can't use e.g. comparators there.

The pattern of using a factory method CardFactory::create also does not make much sense to me. The Grid receives a list of items through the DataProvider (either through setItems or setDataProvider) and the Renderer just processes those items to show them in the UI. You should not create new data objects in the Renderer if you can avoid it.

ollitietavainen
  • 3,900
  • 13
  • 30