首页 > 解决方案 > 有没有办法让组合框像 Vaadin Flow 中的 Select 一样呈现选定的值?

问题描述

例如,在Select组件中,所选值的呈现方式如下所示。但是,当涉及到ComboBox它时,它不会呈现,仅在下拉菜单中显示,如下所示。我需要使用,ComboBox因为我需要搜索功能,即在输入值时选择项目,因为可能有很多值。Select理想情况下,合并and会很棒,ComboBox但除非我想知道是否有办法呈现所选值。

标签: vaadinvaadin-flowvaadin14

解决方案


您不能使用任意渲染器,因为文本输入是文本输入。正如问题下方的评论中所指出的,您真正想要的是输入值前面的图标,虽然 ComboBox 中没有很好的 API 用于此目的,但您可以使用vaadin-text-field输入。我已经使用此处的食谱食谱改编了一个示例。请注意,有一个增强请求可以更轻松地处理 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");
        }
    }
}

推荐阅读