com.vaadin.flow.component.listbox.MultiSelectListBox Maven / Gradle / Ivy
/**
* Copyright 2000-2024 Vaadin Ltd.
*
* This program is available under Vaadin Commercial License and Service Terms.
*
* See {@literal } for the full
* license.
*/
package com.vaadin.flow.component.listbox;
import java.util.Collections;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import com.vaadin.flow.data.selection.MultiSelect;
import com.vaadin.flow.data.selection.MultiSelectionEvent;
import com.vaadin.flow.data.selection.MultiSelectionListener;
import com.vaadin.flow.shared.Registration;
import elemental.json.Json;
import elemental.json.JsonArray;
/**
* Server-side component for the {@code vaadin-list-box} element with
* multi-selection.
*
* @author Vaadin Ltd
*
* @param
* the type of the items contained by this component
* @see ListBox
*/
public class MultiSelectListBox
extends ListBoxBase, T, Set>
implements MultiSelect, T> {
/**
* Creates a new list box component with multi-selection.
*/
public MultiSelectListBox() {
super("selectedValues", JsonArray.class, Collections.emptySet(),
MultiSelectListBox::presentationToModel,
MultiSelectListBox::modelToPresentation);
getElement().setProperty("multiple", true);
}
private static Set presentationToModel(MultiSelectListBox listBox,
JsonArray presentation) {
Set modelValue = IntStream.range(0, presentation.length())
.map(i -> (int) presentation.getNumber(i))
.mapToObj(index -> listBox.getItems().get(index))
.collect(Collectors.toSet());
return Collections.unmodifiableSet(modelValue);
}
private static JsonArray modelToPresentation(
MultiSelectListBox listBox, Set model) {
JsonArray array = Json.createArray();
model.stream().map(listBox.getItems()::indexOf)
.forEach(index -> array.set(array.length(), index));
return array;
}
/**
* Sets the value of this component. If the new value is not equal to the
* previous value, fires a value change event.
*
* The component doesn't accept {@code null} values. The value of multi
* select list box without any selected items is an empty set. You can use
* the {@link #clear()} method to set the empty value.
*
* @param value
* the new value to set, not {@code null}
* @throws NullPointerException
* if value is {@code null}
*/
@Override
public void setValue(Set value) {
Objects.requireNonNull(value,
"Cannot set a null value to multi select list box. "
+ "Use the clear-method to reset the component's value to an empty set.");
super.setValue(value);
}
@Override
public void updateSelection(Set addedItems, Set removedItems) {
Set value = new HashSet<>(getValue());
value.addAll(addedItems);
value.removeAll(removedItems);
setValue(value);
}
/**
* Returns an immutable set of the currently selected items. It is safe to
* invoke other {@code SelectionModel} methods while iterating over the set.
*
* There are no guarantees of the iteration order of the returned set of
* items.
*
* @return the items in the current selection, not {@code null}
*/
@Override
public Set getSelectedItems() {
return getValue();
}
@Override
public Registration addSelectionListener(
MultiSelectionListener, T> listener) {
return addValueChangeListener(event -> listener
.selectionChange(new MultiSelectionEvent<>(this, this,
event.getOldValue(), event.isFromClient())));
}
}