有没有办法让 Combobox 像 Vaadin Flow 中的 Select 一样呈现选定的值?

Is there a way to have the Combobox render the selected value like the Select in Vaadin Flow?

例如在 Select 组件中 selected value is rendered as shown here. However when it comes to the ComboBox it is not rendered, only on the dropdown as shown here。我需要使用 ComboBox 因为我需要搜索功能,即在他们输入值时选择项目,因为可能有很多值。理想情况下,合并 SelectComboBox 会很棒,但除非我想知道是否有办法呈现所选值。

您不能使用任意渲染器,因为文本输入就是文本输入。正如问题下方的评论中所述,您真正想要的是输入值前面的图标,虽然 ComboBox 中没有很好的 API 为此,您可以使用 frankenstein 一起解决方案vaadin-text-field 输入的前缀槽。我已经使用 Cookbook recipe here. Note that there's an enhancement request that would make handling prefix/suffix components in ComboBox easier: 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");
        }
    }
}