Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2000-2024 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.flow.component.checkbox;
import java.io.Serializable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.AbstractSinglePropertyField;
import com.vaadin.flow.component.AttachEvent;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.ComponentUtil;
import com.vaadin.flow.component.HasAriaLabel;
import com.vaadin.flow.component.ItemLabelGenerator;
import com.vaadin.flow.component.Tag;
import com.vaadin.flow.component.UI;
import com.vaadin.flow.component.checkbox.dataview.CheckboxGroupDataView;
import com.vaadin.flow.component.checkbox.dataview.CheckboxGroupListDataView;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.component.shared.ClientValidationUtil;
import com.vaadin.flow.component.shared.HasClientValidation;
import com.vaadin.flow.component.shared.HasThemeVariant;
import com.vaadin.flow.component.shared.HasValidationProperties;
import com.vaadin.flow.component.shared.InputField;
import com.vaadin.flow.component.shared.SelectionPreservationHandler;
import com.vaadin.flow.component.shared.SelectionPreservationMode;
import com.vaadin.flow.component.shared.ValidationUtil;
import com.vaadin.flow.component.shared.internal.ValidationController;
import com.vaadin.flow.data.binder.Binder;
import com.vaadin.flow.data.binder.HasItemComponents;
import com.vaadin.flow.data.binder.HasValidator;
import com.vaadin.flow.data.binder.Validator;
import com.vaadin.flow.data.provider.DataChangeEvent;
import com.vaadin.flow.data.provider.DataProvider;
import com.vaadin.flow.data.provider.DataProviderWrapper;
import com.vaadin.flow.data.provider.DataViewUtils;
import com.vaadin.flow.data.provider.HasDataView;
import com.vaadin.flow.data.provider.HasListDataView;
import com.vaadin.flow.data.provider.IdentifierProvider;
import com.vaadin.flow.data.provider.InMemoryDataProvider;
import com.vaadin.flow.data.provider.ItemCountChangeEvent;
import com.vaadin.flow.data.provider.KeyMapper;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.data.provider.Query;
import com.vaadin.flow.data.renderer.ComponentRenderer;
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.function.SerializableConsumer;
import com.vaadin.flow.function.SerializableFunction;
import com.vaadin.flow.function.SerializablePredicate;
import com.vaadin.flow.shared.Registration;
import elemental.json.Json;
import elemental.json.JsonArray;
/**
* CheckBoxGroup is a multi-selection component where items are displayed as
* check boxes.
*
* Use CheckBoxGroup to group related items. Individual checkboxes should be
* used for options that are not related to each other in any way.
*
Validation
*
* CheckboxGroup comes with a built-in validation mechanism that verifies that
* at least one checkbox is selected when
* {@link #setRequiredIndicatorVisible(boolean) required} is enabled.
*
* Validation is triggered whenever the user initiates a value change by
* toggling a checkbox. Programmatic value changes trigger validation as well.
* If validation fails, the component is marked as invalid and an error message
* is displayed below the group.
*
* The required error message can be configured using either
* {@link CheckboxGroupI18n#setRequiredErrorMessage(String)} or
* {@link #setErrorMessage(String)}.
*
* For more advanced validation that requires custom rules, you can use
* {@link Binder}. Please note that Binder provides its own API for the required
* validation, see {@link Binder.BindingBuilder#asRequired(String)
* asRequired()}.
*
* However, if Binder doesn't fit your needs and you want to implement fully
* custom validation logic, you can disable the built-in validation by setting
* {@link #setManualValidation(boolean)} to true. This will allow you to control
* the invalid state and the error message manually using
* {@link #setInvalid(boolean)} and {@link #setErrorMessage(String)} API.
*
* @author Vaadin Ltd
*/
@Tag("vaadin-checkbox-group")
@NpmPackage(value = "@vaadin/polymer-legacy-adapter", version = "24.5.3")
@JsModule("@vaadin/polymer-legacy-adapter/style-modules.js")
@NpmPackage(value = "@vaadin/checkbox-group", version = "24.5.3")
@JsModule("@vaadin/checkbox-group/src/vaadin-checkbox-group.js")
public class CheckboxGroup
extends AbstractSinglePropertyField, Set>
implements HasAriaLabel, HasClientValidation,
HasDataView>, HasItemComponents,
InputField, Set>, Set>,
HasListDataView>,
HasThemeVariant, HasValidationProperties,
HasValidator>, MultiSelect, T> {
private static final String VALUE = "value";
private final KeyMapper keyMapper = new KeyMapper<>(this::getItemId);
private final AtomicReference> dataProvider = new AtomicReference<>(
DataProvider.ofItems());
private SerializablePredicate itemEnabledProvider = item -> isEnabled();
private ItemLabelGenerator itemLabelGenerator = String::valueOf;
private ItemHelperGenerator itemHelperGenerator = item -> null;
private ComponentRenderer extends Component, T> itemRenderer;
private Registration dataProviderListenerRegistration;
private int lastNotifiedDataSize = -1;
private volatile int lastFetchedDataSize = -1;
private SerializableConsumer sizeRequest;
private CheckboxGroupI18n i18n;
private Validator> defaultValidator = (value, context) -> {
boolean fromComponent = context == null;
// Do the required check only if the validator is called from the
// component, and not from Binder. Binder has its own implementation
// of required validation.
boolean isRequired = fromComponent && isRequiredIndicatorVisible();
return ValidationUtil.validateRequiredConstraint(
getI18nErrorMessage(CheckboxGroupI18n::getRequiredErrorMessage),
isRequired, getValue(), getEmptyValue());
};
private ValidationController, Set> validationController = new ValidationController<>(
this);
private SelectionPreservationHandler selectionPreservationHandler;
/**
* Creates an empty checkbox group
*/
public CheckboxGroup() {
super("value", Collections.emptySet(), JsonArray.class,
CheckboxGroup::presentationToModel,
CheckboxGroup::modelToPresentation);
addValueChangeListener(e -> validate());
initSelectionPreservationHandler();
}
/**
* Creates an empty checkbox group with the defined label.
*
* @param label
* the label describing the checkbox group
* @see #setLabel(String)
*/
public CheckboxGroup(String label) {
this();
setLabel(label);
}
/**
* Creates a checkbox group with the defined label and populated with the
* items in the collection.
*
* @param label
* the label describing the checkbox group
* @param items
* the items to be shown in the list of the checkbox group
* @see #setLabel(String)
* @see #setItems(Collection)
*/
public CheckboxGroup(String label, Collection items) {
this();
setLabel(label);
setItems(items);
}
/**
* Creates a checkbox group with the defined label and populated with the
* items in the array.
*
* @param label
* the label describing the checkbox group
* @param items
* the items to be shown in the list of the checkbox group
* @see #setLabel(String)
* @see #setItems(Object...)
*/
@SafeVarargs
public CheckboxGroup(String label, T... items) {
this();
setLabel(label);
setItems(items);
}
/**
* Constructs a checkbox group with a value change listener.
*
* @param listener
* the value change listener to add
* @see #addValueChangeListener(ValueChangeListener)
*/
public CheckboxGroup(
ValueChangeListener, Set>> listener) {
this();
addValueChangeListener(listener);
}
/**
* Constructs a checkbox group with the defined label and a value change
* listener.
*
* @param label
* the label describing the checkbox group
* @param listener
* the value change listener to add
* @see #setLabel(String)
* @see #addValueChangeListener(ValueChangeListener)
*/
public CheckboxGroup(String label,
ValueChangeListener, Set>> listener) {
this(label);
addValueChangeListener(listener);
}
/**
* Constructs a checkbox group with the defined label, a value change
* listener and populated with the items in the array.
*
* @param label
* the label describing the checkbox group
* @param listener
* the value change listener to add
* @param items
* the items to be shown in the list of the checkbox group
* @see #setLabel(String)
* @see #addValueChangeListener(ValueChangeListener)
* @see #setItems(Object...)
*/
@SafeVarargs
public CheckboxGroup(String label,
ValueChangeListener, Set>> listener,
T... items) {
this(label, listener);
setItems(items);
}
@Override
protected void onAttach(AttachEvent attachEvent) {
super.onAttach(attachEvent);
ClientValidationUtil.preventWebComponentFromModifyingInvalidState(this);
}
@Override
public CheckboxGroupDataView setItems(
DataProvider dataProvider) {
setDataProvider(dataProvider);
return getGenericDataView();
}
@Override
public CheckboxGroupDataView setItems(
InMemoryDataProvider inMemoryDataProvider) {
// We don't use DataProvider.withConvertedFilter() here because it's
// implementation does not apply the filter converter if Query has a
// null filter
DataProvider convertedDataProvider = new DataProviderWrapper>(
inMemoryDataProvider) {
@Override
protected SerializablePredicate getFilter(Query query) {
// Just ignore the query filter (Void) and apply the
// predicate only
return Optional.ofNullable(inMemoryDataProvider.getFilter())
.orElse(item -> true);
}
};
return setItems(convertedDataProvider);
}
@Override
public CheckboxGroupListDataView setItems(
ListDataProvider dataProvider) {
setDataProvider(dataProvider);
return getListDataView();
}
/**
* Gets the list data view for the checkbox group. This data view should
* only be used when the items are in-memory and set with:
*
*
{@link #setItems(Collection)}
*
{@link #setItems(Object[])}
*
{@link #setItems(ListDataProvider)}
*
* If the items are not in-memory an exception is thrown.
*
* @return the list data view that provides access to the data bound to the
* checkbox group
*/
@Override
public CheckboxGroupListDataView getListDataView() {
return new CheckboxGroupListDataView<>(this::getDataProvider, this,
this::identifierProviderChanged,
(filter, sorting) -> rebuild());
}
/**
* Gets the generic data view for the checkbox group. This data view should
* only be used when {@link #getListDataView()} is not applicable for the
* underlying data provider.
*
* @return the generic DataView instance implementing
* {@link CheckboxGroupDataView}
*/
@Override
public CheckboxGroupDataView getGenericDataView() {
return new CheckboxGroupDataView<>(this::getDataProvider, this,
this::identifierProviderChanged);
}
private void initSelectionPreservationHandler() {
selectionPreservationHandler = new SelectionPreservationHandler<>(
SelectionPreservationMode.DISCARD) {
@Override
public void onPreserveAll(DataChangeEvent dataChangeEvent) {
// NO-OP
}
@Override
public void onPreserveExisting(DataChangeEvent dataChangeEvent) {
Map