有没有办法让组合框像 Vaadin Flow 中的 Select 一样渲染所选值?

问题描述 投票:0回答:1

例如,在

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

vaadin vaadin-flow vaadin14
1个回答
7
投票

编辑添加:该功能已通过 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");
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.