Composite component ValueChangeEvent

Hi, I made this composite component in jmix 1.6:

JMix 1.6 ->
class MasterDataField :
    CompositeComponent<CssLayout>(),
    Field<BaseMasterData>,
    CompositeWithCaption,
    CompositeWithHtmlCaption,
    CompositeWithHtmlDescription,
    CompositeWithIcon,
    CompositeWithContextHelp,
    Focusable, Logging {

It is designed to display either a EntityComboBox or a RadioButtonGroup depending on various parameters. Only one of the two is visible at any given time. This MasterDataField is used hundreds of times throughout my app.
I’m migrating my app to JMix 2 and MasterDataField became:

JMix 2.5 ->
class MasterDataField : Composite<VerticalLayout>(),
    SupportsValidation<BaseMasterData>,
    SupportsStatusChangeHandler<AbstractSinglePropertyField<*, BaseMasterData>>,
    ComponentValueChangeEvent<AbstractSinglePropertyField<*, BaseMasterData>, BaseMasterData>, BaseMasterData, BaseMasterData>,
    SupportsValueSource<BaseMasterData>,
    HasRequired,
    HasTitle,
    HasLabel,
    Logging {
{

the problem is that the ComponentValueChangeEvent is not triggred on MasterDataField
It worked in 1.6. How should I migrated this class in your opinion ?

thoughts:
I understand that the ComponentValueChangeEvent is in AbstractField so my composite should implement Composite<AbstractSinglePropertyField<*, *>> but I can’t do that because it should contains 2 fields. :grimacing:
I can’t decide what type the main field is in the initContent, it can only be done in the onAttach (because I need ValueSource to decide and it is initialized after initContent if I’m not mistaken). :face_with_peeking_eye:
Maybe I can create a class SmartLayout: JmixLayout, AbstractSinglePropertyField<*, *> that push listeners to all children. then have Composite<SmartLayout> (too complicated :yawning_face:)

I tried to inherit from CustomField<BaseMasterData>()like in the doc but the event isn’t called and the field do not appear in the studio button “generate handler”.

Hello!

In Jmix 1.6 your implement Field interface which indicates that your complicated component behaves as field. In Jmix 2.5 you should do the same, at least you should implement com.vaadin.flow.component.HasValue interface.

I prepared a demo project as an example of simplified MasterDataField: demo.zip (1.0 MB)

It uses its own field delegate and value binding. Based on ValueSource it creates TypedTextField or Checkbox.
Take a look at how other fields in Jmix are implemented. For instance, JmixSelect component, it uses FieldDelegate bean that share common behavior for fields and creates data binding.

Thank you for you answer. I ended up make it work in a simpler version by implementing the interface HasValue<HasValue.ValueChangeEvent<BaseMasterData>, BaseMasterData>. It’s was simpler for me as I’m not a Jmix developer, working with delegates and all the inner gears of Jmix is not easy. It’s easier to just forward the valueSource and let the inner ComboBox handle labels, data and stuff…

    override fun setValueSource(valueSource: ValueSource<BaseMasterData>?) {
        (valueSource as ContainerValueSource<*,*>).setApplicationContext(applicationContext)
        entityComboBox.valueSource = valueSource
//     TODO   radioButton.valueSource = valueSource
    }