Программное создание столбца с вычисляемыми значениями

Хочу в dataGrid выводить дополнительный столбец, значения в котором высчитываются по некому алгоритму. Например значение из другого столбца, умноженное на коэффициент, который на форме ввел пользователь.
Делал через addComponentColumn в onInit, или через rendered. Все показывается отлично.

rid.Column<CheholCat> zap1 = cheholCatsDataGrid.addComponentColumn(cheholCat -> {
            Span newSpan = uiComponents.create(Span.class);
            newSpan.setText(cheholCat.getDlina().toString());

            return newSpan;

        }).setHeader("Запас").setAutoWidth(true).setSortable(true);

Но проблема в том что столбец не сортируется при клике на header данной колонки. Как сделать чтобы работала сортировка? Может что то использовать вместо Span(надо выводить Integer значение)?
У коллег в Cube через generator и возращение Component Table.PlainText все работает по умолчанию.

Jmix version: 2.2.3
Jmix Studio plugin version: 2.2.4-232
IntelliJ version: IntelliJ IDEA 2023.2.6 (Community Edition)

Здравствуйте, @ermolaevde.

Сортировка будет работать если атрибут объявлен в сущности, иначе нужно дописать свой comparator для колонки.

Например, сущность Order, где tax - атрибут, вычисляемый на основе атрибута amount:

@JmixEntity
@Table(name = "ORDER_")
@Entity(name = "Order_")
public class Order {
    @JmixGeneratedValue
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @Column(name = "AMOUNT", nullable = false, precision = 19, scale = 2)
    @NotNull
    private BigDecimal amount;
    
    @DependsOnProperties({"amount"})
    @JmixProperty
    public BigDecimal getTax() {
        return amount != null ? amount.multiply(new BigDecimal("0.13")) : null;
    }

    //getters, setters
}

Тогда, в стандартном в data grid можно добавить колонку с property="tax" и сортировка будет работать:

        <dataGrid id="ordersDataGrid"
                  width="100%"
                  minHeight="20em"
                  dataContainer="ordersDc"
                  columnReorderingAllowed="true">
           ...
            <columns resizable="true">
                <column property="amount"/>
                <column property="tax"/>
            </columns>
        </dataGrid>

С уважением,
Мария.

Спасибо большое.
А если мне надо высчитывать столбец на основе существующего + некого коэффициента, который пользователь вводит на форме и на этой же форме показываю таблицу с сущностями. Есть какой то правильный способ передать эту переменную из формы в данную сущность?

Можете попробовать создать Column на основе существующего поля, при этом переопределить его Renderer(где будете вычислять значения). Этот подход сработает, если “естественный” порядок сортировки данных первоначального столбца не меняется(к примеру, если вы используете умножение на коэфициэнт).

Также можете ознакомиться с разделом “Специализированная сортировка” статьи " Использование компонентов данных". Использование компонентов данных :: Документация Jmix Обратите внимание, что в зависимости о того, используется ли у вас пагинация для таблицы или нет, а также от количества данных, может использоваться или сортировка в памяти, или может отправляться запрос к базе данных.

2 симпатии

В качестве примера к первому подходу могу привести следующий код:

        <dataGrid id="someEntitiesDataGrid"
                  width="100%"
                  minHeight="20em"
                  dataContainer="someEntitiesDc"
                  columnReorderingAllowed="true"
                  selectionMode="MULTI">
            <actions>
                <action id="create" type="list_create"/>
                <action id="edit" type="list_edit"/>
                <action id="remove" type="list_remove"/>
            </actions>
            <columns resizable="true">
                <column property="name"/>
                <column property="number"/>
            </columns>
        </dataGrid>
    @Supply(to = "someEntitiesDataGrid.number", subject = "renderer")
    private Renderer<SomeEntity> someEntitiesDataGridNumberRenderer() {
        return new TextRenderer<>(someEntity -> Integer.toString(someEntity.getNumber() * 2));
    }