Value calculate for each row in a table

Hello,

following the quick start video of part 4, I calculated the total value of order in orderEdit with addCollectionChangeListener.

To do this I used a transient attribute. What I want to do now is to calculate the same value in orderBrowse for each row in the table.

In general I would like an example of calculation of values for each row of a table,
a simple price multiplied by quantity.

Thanks in advance.

Hi,

you have two options for calculatable values in a Table:

  1. MetaProperty
  2. Table generated column

In the first case you can define simple calculation logic right in the entity:


@Table(name = "METADEMO_PRODUCT")
@Entity(name = "metademo$Product")
public class Product extends StandardEntity {
    private static final long serialVersionUID = -8767718329931420801L;

    @Column(name = "TITLE", nullable = false, unique = true)
    protected String title;

    @Column(name = "COUNT_", nullable = false)
    protected Integer count;

    @Column(name = "PRICE", nullable = false)
    protected Integer price;

    @MetaProperty(related = {"price", "count"}) // it depends on price and count
    public Integer getCost() {
        return getCount() * getPrice();
    }

    // ... getters and setters
}

And then you can define it in a Table as usual column:


<table id="productsTable"
       width="100%">
    <columns>
        <column id="title"/>
        <column id="count"/>
        <column id="price"/>
        <column id="cost"/>
    </columns>
    <rows datasource="productsDs"></rows>
</table>

In the second case column functionality will be limited if there is no corresponding attribute in an entity, for example it will be non sortable and grouping of such a column is not supported. But in generated columns you can use UI context and values entered by user in UI:


public class ProductBrowse extends AbstractLookup {
    @Inject
    private Table<Product> productsTable;
    @Inject
    private ComponentsFactory componentsFactory;

    @Override
    public void init(Map<String, Object> params) {
        super.init(params);

        productsTable.addGeneratedColumn("cost", entity -> {
            Label label = componentsFactory.createComponent(Label.class);
            label.setValue(entity.getCount() * entity.getPrice());
            return label;
        });
    }
}

If you have repeated logic in your application you can always extract it to some usual Java class and call it from MetaProperty or generated column.

Thanks for your response Yuriy.

Still referring to the example in the quick start part 4, I was trying to @Inject CollectionDatasource for Order entity but in the init method is null, even though I do not understand why …

However, if I want to calculate in browserOrder the total order for each row in the table, which depends on the sum of the order lines, how would you do?

Be patient, I am at the beginning and a little confused.

Thank you.

I’ve checked quick start part 4 and everything works as expected. Could you please attach small demo project where you have null CollectionDatasource in the init method?

In case of simple calculation of totals I would use simple meta property with one getter method defined in an Entity class, because I will be able to use this logic in all my screens and services and this formula is small enough to not extract it to a separate class/service.

Thanks Yuriy,

I was able to calculate the total I requested to you, both with my java class, either with a ServiceBean by different methods, both with EntityManager, either with DataManager, both using getLines of the Order entity.

I am very satisfied and I am continuing to study your documentation.

Thanks again for your help.