复合组件

复合组件是由其他多个组件组合而成。与 fragments 类似,复合组件能复用一些展示布局和逻辑。

下列情况我们建议使用复合组件:

  • 组件功能可以用已有的可视化组件以组合的方式来实现。

    如果需要非标准功能,请 集成 JavaScript 库创建一个 Web 组件

  • 组件相对比较简单,本身并不会加载或者保存数据。否则的话,考虑创建一个 fragment。

使用复合组件

下面的示例中,ColorComponent 组件通过组合 ColorPickerspan 实现。其中 ColorPicker 是在 使用 Element API 部分创建的。span 用于显示文本。

import com.vaadin.flow.component.Composite;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.component.orderedlayout.FlexComponent;
import com.vaadin.flow.component.orderedlayout.HorizontalLayout;

public class ColorComponent extends Composite<HorizontalLayout> { (1)

    private final ColorPicker colorPicker;

    public ColorComponent() {
        colorPicker = new ColorPicker();
        Span valueLabel = new Span(colorPicker.getValue());

        colorPicker.addValueChangeListener(event ->
                valueLabel.setText(event.getValue()));

        getContent().add(colorPicker, valueLabel); (2)
    }

    @Override
    protected HorizontalLayout initContent() { (3)
        HorizontalLayout content = super.initContent();
        content.setAlignItems(FlexComponent.Alignment.CENTER);

        return content;
    }

    public String getValue() { (4)
        return colorPicker.getValue();
    }

    public void setValue(String value) {
        colorPicker.setValue(value);
    }
}
1 Composite 基类使用根组件类型作为泛型参数。
2 根组件可以通过 getContent() 方法获取。
3 当第一次请求该复合组件的内容时,会调用 initContent() 方法。此方法应当初始化复合组件的组件结构,并返回根组件。默认情况下,此方法使用反射根据子类的泛型类型实例化组件。
4 复合组件的公共 API委托给 colorPicker 组件实现。
composite component
Figure 1. 视图布局中的复合组件

使用 CustomField

CustomField 是一个基类,可以将多个组件包装成一个单一输入控件。提供标准输入字段功能,例如标签、帮助文本和验证。可以用来创建自定义输入组件。

上面的示例可以用 CustomField 重写:

import com.vaadin.flow.component.customfield.CustomField;
import com.vaadin.flow.component.html.Span;
import com.vaadin.flow.dom.Style;

public class ColorField extends CustomField<String> {

    private final ColorPicker colorPicker;

    public ColorField() {
        colorPicker = new ColorPicker();
        Span valueLabel = new Span(colorPicker.getValue());
        valueLabel.getStyle().setMarginInlineStart("var(--lumo-space-s)");

        colorPicker.addValueChangeListener(event -> {
            valueLabel.setText(event.getValue());
        });

        add(colorPicker, valueLabel);
    }

    @Override
    protected String generateModelValue() {
        return colorPicker.getValue();
    }

    @Override
    protected void setPresentationValue(String presentationValue) {
        colorPicker.setValue(presentationValue);
    }
}

组件实现完成后,可以在视图中使用,示例:

@Subscribe
public void onInit(final InitEvent event) {
    ColorField customField = new ColorField();
    customField.setLabel("Color Field");
    customField.setHelperText("Helper text");
    getContent().add(customField);
}
custom field
Figure 2. 视图布局中的 CustomField