How to filter values of second lookup acordly of the selected value of first lookup

Hello I am new to the platform and I need all the help possible to learn how to use the tool
I have two lookups “Countries” and “Cities” and I would like to filter the “Cities” according to the selected “Country”, how can I do this task?

I need to do this on the sales registration screen

my database model
== Country table ==
ID
Name

== City table ==
	ID
	Name
	CountryID
	
== Sale table ==
	ID
	Date
	CountryID
	CityID
	Ammount
	etc...

Thank you for any help

I created an image to better explain the problem
I’m not using any visual assistant so I don’t know if this type of problem can be solved using the paid cuba studio assistants

They could help me solve this problem so that I can continue the evaluation of cuba studio, I have already looked at all the documentation and I have not found any example on how to solve this problem and I think this is something very simple to do

print

I am evaluating the cuba studio before making the purchase, what do I have to do to be able to have an answer here on the forum?
I activated the evaluation period and I already have access to the design screens but I still can’t find an option where I make a pickerField dependent on another pickerField in add/edit screen

I need cidadeField to be loaded according to the value selected in estadoField

print

Hi,

You can use data load coordinator for that task:

DataLoadCoordinator - CUBA Platform. Developer’s Manual - But you should use lookup fields for it.

When you want to use picker fields, you need to programmatically pass the selected value to the city browse screen in order to filter it in this datacontainer.

Cheers
Mario

Hi @mario ,

I had already seen this part of the documentation, I need to use pickerField because my city table has more than 30,000 records,
could you provide an example of how to perform this task via code?

Thank you.

@mario,

I can get the value of the PickerField “estado” in controller but I don’t know what to do now with this
value to filter the PickerField “cidade”

public class BairroEdit extends StandardEditor {
@Inject
private Notifications notifications;
@Inject
private PickerField estadoField;
@Inject
private PickerField cidadeField;

@Subscribe("estadoField")
public void onEstadoFieldValueChange(HasValue.ValueChangeEvent<Estado> event) {
    Estado estado = event.getValue();
    if(estado != null) {
        notifications.create()
                .withCaption("Key: " + estado.getSigla() + "\nValue: " + estado.getNome())
                .show();
    }
}

}

Hi,

so you mean 30,000 records per Country or 30,000 records overall?

Because if you only have 30,000 records overall in the table it is not a problem. The data load coordinator will only perform the query once you selected a value for the country. Then the result set will significantly less, right?

Cheers
Mario

If you still want to use the picker field, you can use the screenOptionsSupplier example from the docs:

https://doc.cuba-platform.com/manual-latest/LookupAction.html

like this:

@Install(to = "cityField.lookup", subject = "screenOptionsSupplier")
private ScreenOptions cityFieldLookupScreenOptionsSupplier() {
    return new MapScreenOptions(ParamsMap.of("country", countryField.getValue()));
}

Then in the CityBrowse screen, you can use the init method to get a reference to the parameter and set this in the dataSource.

I couldn’t understand how to perform this task, would it be possible to create an example project?
This situation that I went through was very simplified, in reality the data model is just like that:

a “Country” has many “States”
a “State” have many “Cities”
a “City” has many “Neighborhoods”
a “Neighborhood” has many “Addresses”

records per table:

  • Country: 200
  • State: +5000
  • City: +100,000
  • Neighborhood: +1,200,000

I need to create a registration screen where I can filter all these levels until I reach the address
and I need to use PickerField for this task

Hi,

as this question comes up quite often and we only had an example from pre CUBA 7.x I updated the example with the mentioned dataLoadCoordinator.

I use the petclinic example to create an address dependent lookup for Owners. The example is located here: GitHub - mariodavid/cuba-example-dependent-lookup

I will paste the README in here as well:

CUBA Petclinic - Example: Dependent Lookup Fields

This Example extends the CUBA Petclinic with dependent lookup components in order to select a hierarchical owner address.

cuba-example-dependent-lookup-overview

In the address-edit.xml the dependencies between the lookup fields are connected via the dataLoadCoordinator component:

<data>
    <!-- ... -->
    <collection id="countriesDc" class="com.haulmont.sample.petclinic.entity.owner.address.Country"
      view="_minimal">
      <loader id="countriesDl">
        <query>
          <![CDATA[select e from petclinic_Country e]]>
        </query>
      </loader>
    </collection>
    <collection id="statesDc" class="com.haulmont.sample.petclinic.entity.owner.address.State"
      view="_minimal">
      <loader id="statesDl">
        <query>
          <![CDATA[select e from petclinic_State e where e.country = :container_countriesDc]]>
        </query>
      </loader>
    </collection>
    <collection id="citiesDc" class="com.haulmont.sample.petclinic.entity.owner.address.City"
      view="_minimal">
      <loader id="citiesDl">
        <query>
          <![CDATA[select e from petclinic_City e where e.state = :container_statesDc]]>
        </query>
      </loader>
    </collection>
    <collection id="streetsDc" class="com.haulmont.sample.petclinic.entity.owner.address.Street"
      view="_minimal">
      <loader id="streetsDl">
        <query>
          <![CDATA[select e from petclinic_Street e where e.city = :container_citiesDc]]>
        </query>
      </loader>
    </collection>
  </data>

  <facets>
    <dataLoadCoordinator auto="true"/>
  </facets>

The dynamic removal of the dependent values once a higher level entry changes is done programmatically in the AddressEdit controller like this:

public class AddressEdit extends StandardEditor<Address> {

    @Inject
    protected LookupField<Street> streetField;
    @Inject
    protected LookupField<City> cityField;
    @Inject
    protected LookupField<State> stateField;

    @Subscribe("cityField")
    protected void onCityFieldValueChange(ValueChangeEvent<City> event) {
        clearField(streetField, event);
    }

    @Subscribe("stateField")
    protected void onStateFieldValueChange(ValueChangeEvent<State> event) {
        clearField(cityField, event);
    }

    @Subscribe("countryField")
    protected void onCountryFieldValueChange(ValueChangeEvent<Country> event) {
        clearField(stateField, event);
    }

    private void clearField(LookupField<? extends Entity> field, ValueChangeEvent<? extends Entity> event) {
        if (event.getPrevValue() != event.getValue()) {
            field.setValue(null);
        }
    }
}

I hope this helps.

Cheers
Mario

Thank you very much now I fully understand the use of lookupField.
New questions have arisen related to the same subject I don’t know if I can ask right here or I have to open another forum post I am very grateful if you can answer these questions.

  • how to filter with accent insensitive in lookupField?
  • how is the performance / memory consumption of windows server environment that has 200 simultaneous users consulting a lookupField that always returns 6000 records?
  • how to leave the Enum result in UPPER CASE letters?

Congratulations for the great support

hi,

If you are talking about the concrete use-case of country / state / city lookup I would assume those values almost never change. Therefore you can introduce caching in some form or the other. Then you are not doing ongoing DB interactions. You can take a look here: Entity and Query Cache - CUBA Platform. Developer’s Manual

In CUBA you have localization capabilities as one core tenant. You can simply give the uppercase translations. See here: Enum Localization - CUBA Platform. Developer’s Manual

Cheers
Mario

Thank you for your support.
This framework is amazing :slight_smile:

Cheers