I am not a professional developer, programming is just my hobby.
So I ask for help in understanding the following problem.
I use
<properties>
<java.version>21</java.version>
<vaadin.version>24.4.12</vaadin.version>
</properties>
I created a class that extends CustomField:
@FieldDefaults(level = AccessLevel.PRIVATE)
public class ValueCustomComponent extends CustomField<ValueDTO> {
NumberField numberField;
ComboBox<String> comboBox;
ValueDTO value = new ValueDTO();
public ValueCustomComponent() {
initialize();
}
private void initialize() {
this.numberField = new NumberField();
this.comboBox = new ComboBox<>();
comboBox.setItems(List.of("First Value", "Second Value", "Third Value"));
comboBox.setAllowCustomValue(true);
numberField.getElement().setAttribute("disabled", true);
comboBox.addBlurListener(comboBoxBlurEvent -> {
if(comboBox.getValue() != null && !comboBox.getValue().equals(value.getDrug())){
numberField.getElement().setAttribute("disabled", false);
}
});
setValues();
add(comboBox, new Text(" "), numberField);
}
private void setValues() {
if (value.getDrug() != null) {
comboBox.setValue(value.getDrug().toString());
}
if (value.getAmount() != null) {
numberField.setValue(value.getAmount());
}
}
@Override
protected ValueDTO generateModelValue() {
value.setDrug(comboBox.getValue());
value.setAmount(numberField.getValue());
return value;
}
@Override
protected void setPresentationValue(ValueDTO valueDTO) {
comboBox.setValue(valueDTO.getDrug().getValue());
numberField.setValue(valueDTO.getAmount());
}
}
`
Now I'm trying to get a notification when this component loses focus:
@Route(value = "test")
@FieldDefaults(level = lombok.AccessLevel.PRIVATE)
public class TestView extends VerticalLayout {
public TestView() {
ValueCustomComponent valueCustomComponent = new ValueCustomComponent();
valueCustomComponent.addBlurListener(this::onBlur);
add(valueCustomComponent);
}
private void onBlur(BlurNotifier.BlurEvent<CustomField<ValueDTO>> customFieldBlurEvent) {
showNotification(customFieldBlurEvent.getSource().getValue().toString());
}
private void showNotification(String value) {
Notification notification = new Notification(value, 2000, Notification.Position.TOP_CENTER);
notification.addThemeVariants(NotificationVariant.LUMO_SUCCESS);
notification.open();
}
}
But onBlur()
method is never called.
Why doesn't the default implementation of addBlurListener()
work?
What should I do to get addBlurListener()
working?
I tried to find information in the Vaadin documentation and forum, as well as on stackoverflow, but without success.
This is because of how the DOM events work, not so much related to Vaadin itself.
Your custom component essentially has a container element with multiple child elements/components within (comboBox
and numberField
). The children do become active when focused, however, the ValueCustomComponent element never does because the active focus does not automatically bubble up to parent elements.
// not real html, just a visual to show basic dom structure
<ValueCustomComponent>
<ComboBox />
<NumberField />
</ValueCustomComponent>
You can manually fire a blue event from the ValueCustomComponent class like this:
fireEvent(new BlurEvent<ValueCustomComponent>(this, true));
You will need to find a way to track focus (via focus and blur listeners on the comboBox
and numberField
fields) and manually fire a blur event when you're confident the focus has left one of your child fields and is did not move to an another child.