有没有办法让 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
因为我需要搜索功能,即在他们输入值时选择项目,因为可能有很多值。理想情况下,合并 Select
和 ComboBox
会很棒,但除非我想知道是否有办法呈现所选值。
您不能使用任意渲染器,因为文本输入就是文本输入。正如问题下方的评论中所述,您真正想要的是输入值前面的图标,虽然 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");
}
}
}
例如在 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
因为我需要搜索功能,即在他们输入值时选择项目,因为可能有很多值。理想情况下,合并 Select
和 ComboBox
会很棒,但除非我想知道是否有办法呈现所选值。
您不能使用任意渲染器,因为文本输入就是文本输入。正如问题下方的评论中所述,您真正想要的是输入值前面的图标,虽然 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");
}
}
}