ObjectPicker: Filtering problem

I would like to filter object picker data not just by another field/object, but by a property of that object.

I have two objects"TradeFair" and “Hotel”, both of which have a property “City”. “City” is not a string property, it’s a relation, because “City” is an object, too.

Now in my form I want the user to select a TradeFair and then a Hotel, both using the object picker control. For obvious reasons I only want to present a list of hotels from the same city that the fair is in.

I tried to use something like filterBy="TradeFair.city" filterByField="city" but, that does not seem to work. How should I go about this, please?

Thank you!

In your city object, you can have a one-to-many relationship to the trade fair object

property name="trade_fairs" relatedTo="trade_fair" relationship="one-to-many" relationshipKey="city";

In your form, you can filter the hotel by city$trade_fairs.id

<field name="trade_fair" control="objectPicker" object="trade_fair" />
<field name="hotel"      control="objectPicker" object="hotel"      filterBy="trade_fair" filterByField="city$trade_fairs.id" />

The hotel object filter will look like this

filter[ "city$trade_fairs.id" ] = "selected-trade-fair-id";

Hi @choontat, thanks for your suggestion. Unfortunately I cannot do it like this, because my data model obviously is a lot more complex than the little segment I was showing here.

I have solved it now like this:

  1. add a hidden field for the city to the form
<field name="tradefair_city" control="hidden" />
  1. Filter the hotel field by the hidden field
<field binding="Booking.hotel" ... filterBy="tradefair_city" filterByField="city" />

Unfortunately, hidden fields don’t create change events per default, so I had to work around that by

  1. Adding an onchange event to the tradefair field
<field binding="Booking.tradefair" ... attribnames="onchange" attribvalues="setTradefairCity()" />
  • create a corresponding JS function, that reads the value of the tradefair field, retrieves the corresponing city, writes it to the hidden field, and triggers a change event on that hidden field. (I know I could have created the onchange handler with JS as well, I just didn’t want with any handler that was created by the Preside core js).

The critical point is triggering the change event on the hidden field:

const cityField = document.getElementById( "tradefair_city" );
const changeEvent = new Event( "change" );
cityField.dispatchEvent( changeEvent );
  • add that script to Sticker and include it in your handler in preRenderAddRecordForm()
private void function preRenderAddRecordForm( event, rc, prc, args={} ){
   event.include( "js-tradefair-city );
}

In the end it’s not the most elegant solution, but, one that works for my needs. :wink: