例如,在
Select
组件中,所选值呈现如下所示。然而,当涉及到 ComboBox
时,它不会被渲染,仅在下拉列表中显示,如下所示。我需要使用 ComboBox
因为我需要搜索功能,即在输入值时选择项目,因为可能有很多值。理想情况下,合并 Select
和 ComboBox
会很棒,但除非我想知道是否有办法呈现所选值。
编辑添加:该功能已通过 HasPrefix 和 HasSuffix 接口在 Vaadin 24 中实现:https://github.com/vaadin/platform/issues/3637 因此,您可以使用
setPrefixComponent
将前缀 Icon 添加到任何支持它的组件,包括 ComboBox。
您不能使用任意渲染器,因为文本输入就是文本输入。正如问题下面的评论中所指出的,你真正想要的是输入值前面的图标,虽然 ComboBox 中没有很好的 API 来实现这一点,但你可以使用弗兰肯斯坦的前缀槽来组合一个解决方案
vaadin-text-field
输入。我使用Cookbook 食谱在这里改编了一个示例。请注意,有一个增强请求可以使处理 ComboBox 中的前缀/后缀组件变得更容易:https://github.com/vaadin/flow-components/issues/1594
public class AboutView extends Div {
public AboutView() {
ComboBox<Person> comboBox = new ComboBox<>();
comboBox.setItems(getPersons());
// Renderer for the drop down
comboBox.setRenderer(new ComponentRenderer<Div, Person>(person -> {
Div container = new Div();
container.add(person.getIcon().create(), new Span(person.getName()));
return container;
}));
// on value change: either clear the prefix slot or create a new Icon there
comboBox.addValueChangeListener(e -> {
Person p = e.getValue();
if (p == null) {
PrefixUtil.clearSlot(comboBox, "prefix");
return;
}
PrefixUtil.setPrefixComponent(comboBox, p.getIcon().create());
});
comboBox.setItemLabelGenerator(Person::getName);
add(comboBox);
}
public List<Person> getPersons() {
List<Person> persons = new ArrayList<>();
Person person1 = new Person("Foo", VaadinIcon.ARROW_BACKWARD);
Person person2 = new Person("Bar", VaadinIcon.BAR_CHART);
Person person3 = new Person("Baz", VaadinIcon.PUZZLE_PIECE);
persons.add(person1);
persons.add(person2);
persons.add(person3);
return persons;
}
public static class Person {
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
private String name;
public VaadinIcon getIcon() {
return icon;
}
public void setIcon(VaadinIcon icon) {
this.icon = icon;
}
private VaadinIcon icon;
public Person(String name, VaadinIcon icon) {
this.name = name;
this.icon = icon;
}
}
public static class PrefixUtil {
private static Stream<Element> getElementsInSlot(HasElement target,
String slot) {
return target.getElement().getChildren()
.filter(child -> slot.equals(child.getAttribute("slot")));
}
public static void setPrefixComponent(Component target, Component component) {
clearSlot(target, "prefix");
if (component != null) {
component.getElement().setAttribute("slot", "prefix");
target.getElement().appendChild(component.getElement());
}
}
private static void clearSlot(Component target, String slot) {
getElementsInSlot(target, slot).collect(Collectors.toList())
.forEach(target.getElement()::removeChild);
}
private static Component getChildInSlot(HasElement target, String slot) {
Optional<Element> element = getElementsInSlot(target, slot).findFirst();
if (element.isPresent()) {
return element.get().getComponent().get();
}
return null;
}
public static Component getPrefixComponent(Component target) {
return getChildInSlot(target, "prefix");
}
}
}