FlowUI entityComboBox

I am running into this problem:

IllegalStateException: Cannot set a value for a ComboBox without items. Use setItems to populate items into the ComboBox before setting a value.

Anyone stumbled on this issue?

Thanks

1 Like

Im having the same issue…
Work OK on Create… but fails on Edit.
I need the combo box to just Have a string from a query based off the initialized get edited entity. on init event it doesent work because the entity has no value.

I ended up creating a separate hidden field to make this error go away and put events on the combo box to change the value of the field…

Ghetto solution but for a lack of response its something.

<formLayout id="form" dataContainer="webServiceOperationTransformerReferenceDc">
            <responsiveSteps>
                <responsiveStep minWidth="0" columns="1"/>
                <responsiveStep minWidth="40em" columns="2"/>
            </responsiveSteps>
            <textField id="descriptorColumnNameField" property="descriptorColumnName"/>
            <comboBox id="cmbTarget" datatype="string"/>
            <textField id="targetColumnField" property="targetColumn" datatype="string" visible="false"/>
            <comboBox id="cmbReference"  datatype="string"/>
            <textField id="referenceTypeField" property="referenceType" datatype="string" visible="false"/>
        </formLayout>
    @Subscribe
    public void onBeforeShow(final BeforeShowEvent event) {
        List<String> targetColumns = wSService.listRequestColumns(getEditedEntity().getWebServiceOperationTransformer());
        List<String> referenceTypes = wSService.listReferenceCodeTypes();
        cmbTarget.setItems(targetColumns);
        cmbReference.setItems(referenceTypes);
        cmbReference.setValue(getEditedEntity().getReferenceType());
        cmbTarget.setValue(getEditedEntity().getTargetColumn());
    }

    @Subscribe("cmbTarget")
    public void onCmbTargetComponentValueChange(final AbstractField.ComponentValueChangeEvent<JmixComboBox<String>, String> event) {
        targetColumnField.setValue(event.getValue());
    }

    @Subscribe("cmbReference")
    public void onCmbReferenceComponentValueChange(final AbstractField.ComponentValueChangeEvent<JmixComboBox<String>, String> event) {
        referenceTypeField.setValue(event.getValue());
    }

Anyone have a better solution than this? This cant be the right way to do this.

Perhaps a better solution is to defer fetching of comboBox options until they are really needed using the itemsFetchCallback handler.

Let’s consider an example with the Department entity and type attribute which is a simple string:

@JmixEntity  
@Entity  
public class Department {
	// ...
	@Column(name = "TYPE_")  
	private String type;  
	  
	public String getType() {  
	    return type;  
	}  	  
	public void setType(String type) {  
	    this.type = type;  
	}

In a detail view for this entity you will have a comboBox bound to the type attribute:

<layout>  
    <formLayout id="form" dataContainer="departmentDc">  
	    <!-- ... -->
        <comboBox id="typeField" property="type"/>  
    </formLayout>

And in the controller, define an itemsFetchCallback for this comboBox as follows:

public class DepartmentDetailView extends StandardDetailView<Department> {  
  
    @Install(to = "typeField", subject = "itemsFetchCallback")  
    private Stream<String> typeFieldItemsFetchCallback(final Query<String, String> query) {  
        String enteredValue = query.getFilter().orElse("");  
		// here you can safely call getEditedEntity() to get currently edited Department
        return getTypeValues(getEditedEntity()).stream()  
                .filter(type -> type.toLowerCase().contains(enteredValue.toLowerCase()))  
                .skip(query.getOffset())  
                .limit(query.getLimit());  
    }  
	
	// fake method fetching possible type values
    private List<String> getTypeValues(Department department) {  
        if (department == null)  
            throw new IllegalStateException("Cannot fetch department types");  
        return List.of("Administration", "Production", "Other");  
    }  
}

Using itemsFetchCallback solves the chicken-and-egg problem with components initialization, and also improves performance because the fetching method is not called until the user starts selecting a value.

Regards,
Konstantin