Label CustomField with flow only

I have a CustomField like in the first example in https://vaadin.com/docs/latest/components/custom-field
I’d like to use it in different places with different labels without react/lit, just by calling
myCustomField.setLabel("myLabel");
but the label does not appear.

Of course I can propagate the label to the content of the CustomField, but since I have several items in the CustomField (like in the example), the label is only as wide as the first item.

Is this a bug or am I missing something?

Do you have any additional code or context when or where you set the label?

Hmm - I reduced my component to the bare minimum and found the “problem”:
If I tag my component with @Tag(“div”) then setLabel() does not work.
I could reproduce that as well for the simple last example on that page:

@Tag("div")
public class MoneyField extends CustomField<Money> {

    private TextField amount;
    private Select<String> currency;

    public MoneyField(String label) {
        this();
        setLabel(label);
    }

    public MoneyField() {
        amount = new TextField();
        // Sets title for screen readers
        amount.setAriaLabel("Amount");

        currency = new Select<>();
        currency.setItems("AUD", "CAD", "CHF", "EUR", "GBP", "JPY", "USD");
        currency.setWidth("6em");
        currency.setAriaLabel("Currency");

        HorizontalLayout layout = new HorizontalLayout(amount, currency);
        // Removes default spacing
        layout.setSpacing(false);
        // Adds small amount of space between the components
        layout.getThemeList().add("spacing-s");

        add(layout);
    }

    public void addThemeVariant(CustomFieldVariant variant) {
        super.addThemeVariants(variant);
        amount.addThemeVariants(TextFieldVariant.valueOf(variant.name()));
        currency.addThemeVariants(SelectVariant.valueOf(variant.name()));
    }

    @Override
    protected Money generateModelValue() {
        return new Money(amount.getValue(), currency.getValue());
    }

    @Override
    protected void setPresentationValue(Money money) {
        amount.setValue(money.getAmount());
        currency.setValue(money.getCurrency());
    }
}

setLabel() then does not work unless I remove the @Tag(“div”)

So IMHO that is a bug, since (at least according to my understanding) it should be possible to tag a custom field for whatever purpose with anything.

no it’s a misunderstanding of your usage of the API. If you overwrite vaadin-custom-field with div you have to manage the label yourself. How should a div know about the label slot?

1 Like

I think the confusion stems from the fact that you can use the @Tag annotation to define what html element a generic custom Flow component should be based on.

So to clear that up:

  • A generic custom Flow component with @Tag(“div”) means: this is a custom Flow-based component that’s really just a <div> (and whatever I put inside it) on the client side. Since it’s just a container for whatever you put inside, without any parts or functionality of its own, it can be literally any html element.
  • CustomField is an actual Vaadin component with its own client side implementation in the form of a custom html element vaadin-custom-field. The label is part of the client-side implementation of that element. If you replace that custom html element with @Tag("div"), there is no label, because <div> has no such thing.
2 Likes

Thanks for the clarification.