jmix-projects / jmix-old

DEPRECATED. Use https://github.com/jmix-framework/jmix
16 stars 3 forks source link

Convert formatters to beans #499

Closed GlebDurygin closed 4 years ago

GlebDurygin commented 4 years ago

Related to #455

Convert formatters to prototype beans. The legacy API should be moved to compatibility module.

Legacy behaviour

public class CurrencyFormatter implements Function<BigDecimal, String> {

    @Override
    public String apply(BigDecimal bigDecimal) {
        return NumberFormat.getCurrencyInstance(Locale.getDefault()).format(bigDecimal);
    }
}
@Autowired
protected GroupTable<Order> ordersTable;

@Subscribe
public void onInit(InitEvent event) {
    Function currencyFormatter = new CurrencyFormatter();
    ordersTable.getColumn("totalPrice").setFormatter(currencyFormatter);
}

New behaviour

Changes

The formatters have become prototype Beans in JMIX. In compatibility module user can create a formatter using constructor. Also, formatters implement interface io.jmix.ui.component.formatter.Formatter. Example of creating custom formatters:

@Component("sample_CurrencyFormatter")
@Scope("prototype")
public class CurrencyFormatter implements Formatter<BigDecimal> {

    @Override
    public String apply(BigDecimal bigDecimal) {
        return NumberFormat.getCurrencyInstance(Locale.getDefault()).format(bigDecimal);
    }
}
@Component("sample_StringFormatter")
@Scope("prototype")
public class StringFormatter implements Formatter<String> {

    protected final boolean isUppercase;

    public StringFormatter(boolean isUppercase) {
        this.isUppercase = isUppercase;
    }

    @Override
    public String apply(String string) {
        return isUppercase
                ? string.toUpperCase()
                : string.toLowerCase();
    }
}
@Autowired
protected GroupTable<Order> ordersTable;
@Autowired
protected CurrencyFormatter currencyFormatter;

@Subscribe
public void onInit(InitEvent event) {
    // Create a formatter without parameters using an injection
    ordersTable.getColumn("totalPrice").setFormatter(currencyFormatter);

    // Create a formatter without parameters using a bean locator
    ordersTable.getColumn("totalPrice").setFormatter(getBeanLocator().getPrototype(CurrencyFormatter.class));

    // Create a formatter with parameters
    ordersTable.getColumn("name").setFormatter(getBeanLocator().getPrototype(StringFormatter.class, true));
}

Also, <formatter/> element has new attribute - name, that can be used to define the name of bean. First, the name attribute is checked, and then, if it is not defined, the class attribute is checked. For example:

@Component("sample_UppercaseFormatter")
@Scope("prototype")
public class UppercaseFormatter implements Formatter<String> {

    @Override
    public String apply(String s) {
        return s.toUpperCase();
    }
}
        <groupTable id="testEntitiesTable"
                    width="100%"
                    dataContainer="testEntitiesDc">
            <actions>
                <action id="create" type="create"/>
                <action id="edit" type="edit"/>
                <action id="remove" type="remove"/>
            </actions>
            <columns>
                <column id="name">
                    <formatter name="sample_UppercaseFormatter"/>
                </column>
                <column id="lastName">
                    <formatter class="com.company.sample.web.formatter.UppercaseFormatter"/>
                </column>
            </columns>
            <rowsCount/>
            <buttonsPanel id="buttonsPanel"
                          alwaysVisible="true">
                <button id="createBtn" action="testEntitiesTable.create"/>
                <button id="editBtn" action="testEntitiesTable.edit"/>
                <button id="removeBtn" action="testEntitiesTable.remove"/>
            </buttonsPanel>
        </groupTable>
alexbudarov commented 4 years ago

Please consider returning Formatter interface back! https://github.com/jmix-framework/jmix/issues/200 It is essential for high-quality tooling support in Studio.