vaadin / vaadin-core

Home Page:https://vaadin.com/docs/latest/ds/overview

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Suggestion: Add way to modify renderer for selected item for ComboBox

masbaehr opened this issue · comments

I'm trying to make some prettier ComboBoxes like the one shown below. However it feels bad that i can't add the icon to the selected item as well. Currently setItemLabelGenerator allows only a String to be set as label.

image

code:

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ItemLabelGenerator;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.data.renderer.ComponentRenderer;

public class GenderComboBox extends ComboBox<Gender>  {
	
	public GenderComboBox() {
	 
		this.setLabel(this.getTranslation("Gender"));
		this.setItems(Gender.values());
	 
		this.addValueChangeListener(event -> {
			//this.getElement().getStyle().set("--lumo-body-text-color", event.getValue());
		});
		
		this.setItemLabelGenerator(new ItemLabelGenerator<Gender>() {
			@Override
			public String apply(Gender item) {
				return item.label();
			}
		});
		
		
		this.setRenderer(new ComponentRenderer<Component, Gender>(item -> {
			
			Div cd = new Div();
			Label l = new Label(this.getTranslation(item.label()));
			
			 
			Icon vi = null;
			if(item == Gender.FEMALE) {
				vi = new Icon(VaadinIcon.FEMALE);
				vi.setColor("#ff8ee5");
			}
			if(item == Gender.MALE) {
				vi = new Icon(VaadinIcon.MALE);
				vi.setColor("#49d7ff");
			}
			if(item == Gender.UNDEFINED) {
				vi = new Icon(VaadinIcon.QUESTION);
				vi.setColor("black");
			}
			
			cd.add(vi, l);
			return cd;
 
		}));
		
	}
	
	 
	
}

As it seems you only need a small amount of items, I suggest you wait for the upcoming Select component (based on <vaadin-select> which allows you to use the same representation for the items in the list and the field value.

Still, the enhancement suggestion is valid, and has been on our internal wishlist as well for a long time. Maybe at some point :)

I'm now using this solution. If someone comes across this issue.. You could use this code to get something like this:

If someone could tell me how i could make the rounded corner between the items less visible and get the same matching background color for the icon-button it would be a great help :)

image

import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ItemLabelGenerator;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.combobox.ComboBox;
import com.vaadin.flow.component.html.Div;
import com.vaadin.flow.component.html.Label;
import com.vaadin.flow.component.icon.Icon;
import com.vaadin.flow.component.icon.VaadinIcon;
import com.vaadin.flow.data.renderer.ComponentRenderer;

public class GenderComboBox extends Div  {
	
	private ComboBox<Gender> cb;
	private Button button;
	
	public GenderComboBox() {
		
		this.getStyle().set("display", "inline-block");
		
		cb = new ComboBox<Gender>();
		button = new Button();
		
		cb.setLabel(this.getTranslation("Gender"));
		cb.setItems(Gender.values());
	 
		cb.addValueChangeListener(event -> {
			button.setIcon(getGenderIcon(event.getValue()));
			button.setText("");
		});
		
		cb.setItemLabelGenerator(new ItemLabelGenerator<Gender>() {
			@Override
			public String apply(Gender item) {
				return item.label();
			}
		});
		
		cb.setRenderer(new ComponentRenderer<Component, Gender>(item -> {
			Div cd = new Div();
			Label l = new Label(this.getTranslation(item.label()));
			cd.add(getGenderIcon(item), l);
			return cd;
 
		}));
		
		this.add(cb);
		this.add(button);
		
	}
	
	public void setValue(Gender g) {
		cb.setValue(g);
		button.setIcon(getGenderIcon(g));
		button.setText("");
	}
	
	public Icon getGenderIcon(Gender g) {
		Icon i = null;
		if(g == Gender.FEMALE) {
			i = new Icon(VaadinIcon.FEMALE);
			i.setColor("#ff8ee5");
		}
		if(g == Gender.MALE) {
			i = new Icon(VaadinIcon.MALE);
			i.setColor("#49d7ff");
		}
		if(g == Gender.UNDEFINED) {
			i = new Icon(VaadinIcon.QUESTION);
			i.setColor("black");
		}
		return i;
	}
	 
	
}

Hi @masbaehr , did you fix this issue. if yes then please provide me the code which can be use to get language list and their respective flag.
combobox_icon_text_too_close

Unfortunately No i did not fix it. With the current Implementation of ComboBox it is not possible to show the Image. So we need to wait until the Vaadin Team offers a way to set a custom Generator not only for the ItemLabel when it is opened, but also for the label itself.

However there is a workaround which is kinda ugly - but works - Just show a Image on the left of it, give it the same border as the Combobox and adjust the width accordingly. To make it look seamless use getStyle().set("border-right", "none") on the Image and "border-left", "none" for the Combobox

This issue was moved to vaadin/vaadin-combo-box-flow#175

@kuldeepcchetu @masbaehr thank you for the use cases. I have moved the issue to the proper repo as this seems to me more related to the Flow counterpart API request.