multiple EditorComponent on one grid column

I have a grid and for a specific column I am displaying different data using a TextField and a ComboBoxMultiselect. My column looks like this:

Component aaa;
grid.addComponentColumn(probe -> {
	if(probe.getAttributeLabel().toLowerCase().contains("material")) {
		//trasform the value of the attribute material to list
		//probe.getAttributeValue() -> Ceramic;Iron

		Set<String> selectedItems = new HashSet<String>();
		String[] i = probe.getAttributeValue().split(";");
		for (int j = 0; j < i.length; j++) {
			selectedItems.add(i[j]

);
}
ComboBoxMultiselect multiAttributeValueField = new ComboBoxMultiselect();

		multiAttributeValueField.setItems(materialsList);
		multiAttributeValueField.setValue(selectedItems);
		multiAttributeValueField.addStyleName(ValoTheme.COMBOBOXBORDERLESS);
		aaa = multiAttributeValueField;

	}
	else {
		TextField field = new TextField();
		field.addStyleName(ValoTheme.TEXTFIELDBORDERLESS);
		field.setValue(probe.getAttributeValue());
		aaa = field;
	}
	return aaa;
})
.setEditorComponent(aaa, AttributeById::setComponent)
.setCaption("Multi Attribute").setId("MultiAttribute");

But I have the following error:
The method setEditorComponent(C, Setter<AttributeById,Component>) in the type Grid.Column<AttributeById,Component> is not applicable for the arguments (Component, Setter<AttributeById,Component>)

Is there a way to manage the editor in the two different situations?

What is ComboBoxMultiSelect? Do you mean MultiselectComboBox ([add-on]
(https://vaadin.com/directory/component/multiselect-combo-box))?

The method setEditorComponent(Component component, Setter<AttributeById,Component> setter) does not exist. You don’t need to provide a setter there, but instead define a ValueChangeListener on your editorComponent which will then change the value of the underlying item.

And since the same component instance can only be present in the DOM one time, reusing components that were created inside Renderers outside of their scope is not going to end well in most cases.

Also, because without opening the editor of a row the attributeValue is just a String, I would just use a simple TextRenderer for the non-editor state. You can of course still use your componentRenderer, just remove all mentions of aaa. I went for a simple textrenderer in my example for readability reasons

example:

grid.addComponentColumn(probe -> probe.getAttributeValue())
	.setEditorComponent(probe -> {
		if(probe.getAttributeLabel().toLowerCase().contains("material")) {
			//trasform the value of the attribute material to list
			//probe.getAttributeValue() -> Ceramic;Iron

			Set<String> selectedItems = new HashSet<String>();
			String[] i = probe.getAttributeValue().split(";");
			for (int j = 0; j < i.length; j++) {
				selectedItems.add(i[j]
);
			}
			MultiselectComboBox<String>  multiAttributeValueField = new MultiselectComboBox<String>();

			multiAttributeValueField.setItems(materialsList);
			multiAttributeValueField.setValue(selectedItems);
			multiAttributeValueField.addStyleName(ValoTheme.COMBOBOXBORDERLESS);
			
			// Without this, it will not work!
			multiAttributeValueField.addValueChangeListener(event -> {
				String joinedAttributeValues = StringUtils.join(event.getValue(), ";");
				probe.setAttributeValue(joinedAttributeValue);
			});
			
			return multiAttributeValueField;
		}
		else {
			TextField field = new TextField();
			field.addStyleName(ValoTheme.TEXTFIELDBORDERLESS);
			field.setValue(probe.getAttributeValue());
			
			// Without this, it will not work!
			field.addValueChangeListener(event -> {
				probe.setAttributeValue(event);
			}
			
			return field;
		}
	})
	.setCaption("Multi Attribute").setId("MultiAttribute");;

Hello Kaspar,
thank you for the fast answer and great explanations!
I did integrate your solution and I have the following on addComponentColumn: Cannot infer type argument(s) for addComponentColumn(ValueProvider<T,V>)

I have the second error also on setEditorComponent: The target type of this expression must be a functional interface

grid.addComponentColumn(probe -> {
			if (probe.getAttributeLabel().toLowerCase().contains("material")) {
				// trasform the value of the attribute material to list
				// probe.getAttributeValue() -> Ceramic;Iron

				Set<String> selectedItems = new HashSet<String>();
				String[] i = probe.getAttributeValue().split(";");
				for (int j = 0; j < i.length; j++) {
					selectedItems.add(i[j]
);
				}
				ComboBoxMultiselect<String> multiAttributeValueField = new ComboBoxMultiselect<String>();

				multiAttributeValueField.setItems(_materialsList);
				multiAttributeValueField.setValue(selectedItems);
				multiAttributeValueField.addStyleName(ValoTheme.COMBOBOX_BORDERLESS);
				return multiAttributeValueField;

			} else {
				TextField field = new TextField();
				field.addStyleName(ValoTheme.TEXTFIELD_BORDERLESS);
				field.setValue(probe.getAttributeValue());
				return field;

			}
		}).setEditorComponent(probe -> {
			if (probe.getAttributeLabel().toLowerCase().contains("material")) {
				// trasform the value of the attribute material to list
				// probe.getAttributeValue() -> Ceramic;Iron

				Set<String> selectedItems = new HashSet<String>();
				String[] i = probe.getAttributeValue().split(";");
				for (int j = 0; j < i.length; j++) {
					selectedItems.add(i[j]
);
				}
				ComboBoxMultiselect<String> multiAttributeValueField = new ComboBoxMultiselect<String>();

				multiAttributeValueField.setItems(materialsList);
				multiAttributeValueField.setValue(selectedItems);
				multiAttributeValueField.addStyleName(ValoTheme.COMBOBOXBORDERLESS);

				// Without this, it will not work!
				multiAttributeValueField.addValueChangeListener(event -> {
					String joinedAttributeValues = StringUtils.join(event.getValue(), ";");
					probe.setAttributeValue(joinedAttributeValue);
				});

				return multiAttributeValueField;
			} else {
				TextField field = new TextField();
				field.addStyleName(ValoTheme.TEXTFIELDBORDERLESS);
				field.setValue(probe.getAttributeValue());

				// Without this, it will not work!
				field.addValueChangeListener(event -> {
					probe.setAttributeValue(event);
				});

				return field;
			}
		}).setCaption("Multi Attribute").setId("MultiAttribute");

Oooh, I didn’t notice you mean Vaadin 8. Sorry for the confusion, please disregard my last comment!

You could probably do what you ask if the two different HasValue components were of the same type. In your case, one is of type List<String> and the other is for String. Therefore, the Setter that you provide to setEditorComponent will always be of wrong type since it can’t be of both types.

In the end, your problem will boil down to the fact that the grid-method public <C extends HasValue<V> & Component> Column<T, V> setEditorComponent(C editorComponent, Setter<T, V> setter) will not accept just any Component as first parameter, it must be one that extends HasValue<V>, because that’s how C is defined in the full method signature. (Also, shouldn’t the setter be Probe::setAttributeValue?)

That’s one of the reasons why it’s never recommended to store Lists of Strings in a single String using delimiters, or two different properties in one single property. I don’t mean to offend, but it will be beneficial in many regards if you have a solid model design where one value is not interpreted a different way if another value contains “material”. Maybe there was no other way, I don’t know. I’m just trying to help here :wink: