Create a table dynamically with a datasource ValueGroupDatasourceImpl and KeyValueEntity

Hello, I try to generate a table dynamically using a datasource type ValueGroupDatasourceImpl with KeyValueEntity, I also need to add to this table several columns dynamically that will contain the result of a calculation made on different fields of the created table. To finish I would also like to add aggregations type “sum” to several fields of this table. What would be the best method to perform these operations? For the moment the creation of the table dynamically using a datasource of type KeyValueEntitiy has worked me correctly, which I can not create is to create fields dynamically (using addGeneratedColumn) with calculations made on the fields created in the table, I also have not got the aggretation type to work on the created fields.
Any examples or ideas?, I show the code so far.


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

    Map<Jerarquia, List<Analisis>> mapaDatos = generarTablaService.generar();

    ValueGroupDatasourceImpl ds = DsBuilder.create().buildValuesGroupDatasource();


    for (Map.Entry<Jerarquia, List<Analisis>> dato : mapaDatos.entrySet()) {
        KeyValueEntity entidad = new KeyValueEntity();
        //obtengo descripcion de jerarquia
        ds.addProperty("jerarquia", com.albertosancheznieto.tabladinamica.entity.Jerarquia.class);
        ds.addProperty("nivel 1", String.class);
        ds.addProperty("nivel 2", String.class);
        ds.addProperty("nivel 3", String.class);
        ds.addProperty("nivel 4", String.class);
        entidad.setValue("jerarquia", dato.getKey());
        entidad.setValue("nivel 1", dato.getKey().getNivel1());
        entidad.setValue("nivel 2", dato.getKey().getNivel2());
        entidad.setValue("nivel 3", dato.getKey().getNivel3());
        entidad.setValue("nivel 4", dato.getKey().getNivel4());

        for (Analisis a : dato.getValue()) {
            ds.addProperty(a.getConcepto().getDescripcion(), BigDecimal.class);
            entidad.setValue(a.getConcepto().getDescripcion(), a.getImporte());
        }
        ds.addItem(entidad);
    }

    Table laTabla = componentsFactory.createComponent(GroupTable.class);
    laTabla.setDatasource(ds);
    laTabla.setWidth("100%");
    laTabla.setHeight("100%");
    //laTabla.setAggregatable(true);
    //laTabla.addAggregationProperty("compras", AggregationInfo.Type.SUM);

    laTabla.addGeneratedColumn("resultado", entity -> {
        return new Table.PlainTextCell(entity.getInstanceName());
    });


    vbox.add(laTabla);

Thanks and regards.

Hi,

It is possible, but it is no so easy. You have to create columns programmatically and set up aggregation for them.

Example:


public class DemoScreen extends AbstractWindow {
    @Inject
    private ComponentsFactory componentsFactory;
    @Inject
    private Metadata metadata;
    @Inject
    private UuidSource uuidSource;

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

        ValueGroupDatasourceImpl ds = DsBuilder.create()
                .setId("groupDs")
                .setRefreshMode(RefreshMode.NEVER)
                .buildValuesGroupDatasource();
        ds.setIdName("id");

        // register properties
        ds.addProperty("name", String.class);
        ds.addProperty("count", Integer.class);
        ds.addProperty("value", Integer.class);

        // set random data
        ds.addItem(item("Sam Dough", 10, 10));
        ds.addItem(item("Bill Dodson", 12, 30));

        // create table
        GroupTable table = componentsFactory.createComponent(GroupTable.class);
        table.setWidth("100%");
        table.setHeight("100%");

        // enable aggregation
        table.setAggregatable(true);

        // create columns programmatically before we set datasource
        MetaClass metaClass = ds.getMetaClass();

        MetaPropertyPath nameMpp = metaClass.getPropertyPath("name");
        Table.Column nameColumn = new Table.Column(nameMpp, "Name");
        nameColumn.setType(nameMpp.getRangeJavaClass());
        table.addColumn(nameColumn);

        MetaPropertyPath countMpp = metaClass.getPropertyPath("count");
        Table.Column countColumn = new Table.Column(countMpp, "Count");
        countColumn.setType(countMpp.getRangeJavaClass());
        AggregationInfo countAggInfo = new AggregationInfo();
        countAggInfo.setPropertyPath(ds.getMetaClass().getPropertyPath("count"));
        countAggInfo.setType(Type.SUM);
        countColumn.setAggregation(countAggInfo);
        table.addColumn(countColumn);

        MetaPropertyPath valueMpp = metaClass.getPropertyPath("value");
        Table.Column valueColumn = new Table.Column(valueMpp, "value");
        valueColumn.setType(valueMpp.getRangeJavaClass());
        AggregationInfo valueAggInfo = new AggregationInfo();
        valueAggInfo.setPropertyPath(ds.getMetaClass().getPropertyPath("count"));
        valueAggInfo.setType(Type.COUNT);
        valueColumn.setAggregation(valueAggInfo);
        table.addColumn(valueColumn);

        // finally, set datasource
        table.setDatasource(ds);

        add(table);
    }

    public KeyValueEntity item(String name, int count, int value) {
        KeyValueEntity entity = metadata.create(KeyValueEntity.class);
        entity.setValue("id", uuidSource.createUuid());
        entity.setValue("name", name);
        entity.setValue("count", count);
        entity.setValue("value", value);
        return entity;
    }
}

See also sources on github: GitHub - cuba-labs/keyvalue-table-aggregation

Hope it will help you, we will try to simplify Table API in the near future.

…we will try to simplify Table API in the near future.

Is there any simpler way now?

Hello,

add is part of AbstractFrame.
Can you advise how to use this method in Cuba 7?
Here we have …extend Screen (not extend AbstractWindow).

Please see this message: How to use a generic data source in a datagrid or table component? - #3 от пользователя krivopustov - CUBA.Platform