Changing query for datasource in table editor

Hi

I have a editable table which has all my sale items in my sales editor page, in my scenario the item has a position which I have loaded using a datasource, what I want is to filter this for every item added so it only shows the position available for the selected item.

45%20AM

As seen in the image above I want to be able to change the query for every facility detail (position) to match only where the item selected is located please bear in mind in the designer the datasource used is the same for all of them so I can’t change the datasource directly as that would affect all the fields. Please advise on the best way to deal with this.

Kind regards,
Mohamed

Hi Mohamed,

You probably have to abandon the common options datasource for the column and define a custom column with LookupField for which you can provide options via setOptionsList() method.

Hi Konstantin,

I will give it a try if I find any difficulties I will let you know.

Thanks

Hi,

I tried however my issue is that I can’t edit the field directly to reset the option list for when the item changes how can I access the field from the selected row so I can call setOptionList. Also the row is generated with null value for item field so the option list is empty.

Thanks

I have prepared an example for you, it is based on the project at GitHub - cuba-platform/sample-sales-cuba7: CUBA Platform Sample application

Imagine that in the Customer-Order-OrderLines model, the Customer entity should store some “special” order and order line. So the Customer browser should look as follows:

Here when user selects an Order, the list of available OrderLines changes. Selected Order and OrderLine are saved to specialOrder and specialOrderLine attributes of the Customer.

Let’s go through the changes.

Customer entity contains attributes specialOrder and specialOrderLine:

@Table(name = "SALES_CUSTOMER")
@Entity(name = "sales_Customer")
public class Customer extends StandardEntity {
// ...
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SPECIAL_ORDER_ID")
    protected Order specialOrder;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "SPECIAL_ORDER_LINE_ID")
    protected OrderLine specialOrderLine;
// ...

CustomerBrowse class contains methods generating columns. These methods get lookup fields from the cache which saves mappings of Customer instances to corresponding lookup fields. See comments in the code.

@UiController("sales_Customer.browse")
@UiDescriptor("customer-browse.xml")
@LookupComponent("customersTable")
@LoadDataBeforeShow
public class CustomerBrowse extends StandardLookup<Customer> {

    @Inject
    private UiComponents uiComponents;
    @Inject
    private DataManager dataManager;
    @Inject
    private DataComponents dataComponents;
    @Inject
    private DataContext dataContext;

    private Map<Customer, Lookups> customerLookups = new HashMap<>();
    
    private class Lookups {
        LookupField<Order> orderLookup;
        LookupField<OrderLine> orderLineLookup;

        Lookups(Customer customer) {
            // create master lookup and load options for it
            orderLookup = uiComponents.create(LookupField.of(Order.class));
            List<Order> orders = dataManager.load(Order.class)
                    .query("select e from sales_Order e where e.customer = :customer")
                    .parameter("customer", customer)
                    .view(View.MINIMAL)
                    .list();
            orderLookup.setOptionsList(orders);

            // create slave lookup
            orderLineLookup = uiComponents.create(LookupField.of(OrderLine.class));
            // reload slave lookup options on each change of the master value
            orderLookup.addValueChangeListener(event -> {
                if (event.getValue() != null) {
                    List<OrderLine> orderLines = dataManager.load(OrderLine.class)
                            .query("select e from sales_OrderLine e where e.order = :order")
                            .parameter("order", event.getValue())
                            .view(View.MINIMAL)
                            .list();
                    orderLineLookup.setOptionsList(orderLines);
                } else {
                    orderLineLookup.setOptionsList(Collections.emptyList());
                }
                if (!Objects.equals(event.getValue(), event.getPrevValue())) {
                    orderLineLookup.setValue(null);
                }
            });

            // data binding to save selected lookup values to Customer entity
            InstanceContainer<Customer> customerDc = dataComponents.createInstanceContainer(Customer.class);
            customerDc.setItem(customer);
            orderLookup.setValueSource(new ContainerValueSource<>(customerDc, "specialOrder"));
            orderLineLookup.setValueSource(new ContainerValueSource<>(customerDc, "specialOrderLine"));
        }
    }

    // generate column with master lookup
    public Component generateOrderCell(Customer entity) {
        return customerLookups.computeIfAbsent(entity, customer -> new Lookups(entity)).orderLookup;
    }

    // generate column with slave lookup
    public Component generateOrderLineCell(Customer entity) {
        return customerLookups.computeIfAbsent(entity, customer -> new Lookups(entity)).orderLineLookup;
    }

    // clear cache on data refresh
    @Subscribe(id = "customersDc", target = Target.DATA_CONTAINER)
    private void onCustomersDcCollectionChange(CollectionContainer.CollectionChangeEvent<Customer> event) {
        if (event.getChangeType() == CollectionChangeType.REFRESH) {
            customerLookups.clear();
        }
    }

    @Subscribe("commitBtn")
    private void onCommitBtnClick(Button.ClickEvent event) {
        dataContext.commit();
    }
}

The complete project is attached.
sample-sales.zip (108.5 KB)

Hi,

I would like to ask how would I make this compatible with Cuba 6.10.

Thanks

It should look the same except data binding - use datasources instead of data containers and value sources.

Hi,

Everything worked perfectly also migrated to v7 to make things easier, thank you for your time.