Когда пользователь выбирает элемент Grid
, мы можем получить объект, представленный строкой этого элемента.
Например, в Grid< LocalDate
с именем grid
удерживая некоторые java.time.LocalDate
объекты, мы можем получить доступ к объекту SingleSelect
, представляющему текущий выбор.
LocalDate localDate = grid.asSingleSelect().getValue() ;
Если ни одна строка в сетке не выбрана, localDate
в строке выше будет нулевым.
Если Grid
имеет фильтр, примененный к его DataProvider
, отображение некоторых или всех строки могут быть подавлены, чтобы соответствовать элементам в поставщике данных, которые не проходят предикатный тест фильтра.
Когда фильтр активирован, и строки не отображаются на дисплее, и среди них есть выбранная строка, сетка остается отображая некоторые строки. Ни одна из отображаемых строк не выбрана. Поэтому я ожидаю, что объект SingleSelect
будет обновлен, и сообщит о его значении как null
.
Проблема в том, что SingleSelect
является не обновленным в таком случае. SingleSelect
продолжает сообщать свое значение как элемент, больше не отображаемый в сетке.
➥ Это ошибка или функция? Имеет ли смысл SingleSelect
, содержащая значение для элемента, не отображаемого на экране?
➥ Если функция, а не ошибка, то как мне go про очистку другого содержимого на экране? это связано с технически выбранным, но больше не отображаемым элементом сетки?
Я столкнулся с этой проблемой, потому что в моей реальной работе у меня была подробная форма, отображающая детали выбранного элемента в сетке. Мой прослушиватель изменений для поставщика данных срабатывает, когда фильтры активированы. Когда ранее выбранная строка исчезает из поля зрения после фильтрации, мой слушатель пошел тестировать SingleSelect
сетки, чтобы увидеть, не была ли строка больше выбрана, чтобы II мог очистить мою форму детализации, установив для ее связующего компонента значение NULL. Я был удивлен, что SingleSelect
все еще содержал выбранный элемент, несмотря на то, что этот элемент отфильтровывался от отображения в сетке.
dataProvider.addDataProviderListener( ( DataChangeEvent < Invoice > dataChangeEvent ) -> {
if( this.grid.asSingleSelect().isEmpty()) { // ? Surprise! Not empty despite no selected item currently displayed in `Grid`.
invoiceDetailPane.binder.setBean( null );
}
} );
Вот полное приложение, просто небольшая демонстрация поведения.
package work.basil.example;
import com.vaadin.flow.component.AbstractField;
import com.vaadin.flow.component.ClickEvent;
import com.vaadin.flow.component.Key;
import com.vaadin.flow.component.button.Button;
import com.vaadin.flow.component.button.ButtonVariant;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.grid.Grid;
import com.vaadin.flow.component.notification.Notification;
import com.vaadin.flow.component.orderedlayout.VerticalLayout;
import com.vaadin.flow.component.textfield.IntegerField;
import com.vaadin.flow.component.textfield.TextField;
import com.vaadin.flow.data.provider.ListDataProvider;
import com.vaadin.flow.router.Route;
import com.vaadin.flow.server.PWA;
import java.time.LocalDate;
import java.time.Month;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
/**
* The main view contains a button and a click listener.
*/
@Route ( "" )
@PWA ( name = "Project Base for Vaadin", shortName = "Project Base" )
@CssImport ( "./styles/shared-styles.css" )
@CssImport ( value = "./styles/vaadin-text-field-styles.css", themeFor = "vaadin-text-field" )
public class MainView extends VerticalLayout
{
private Grid < LocalDate > grid;
private IntegerField yearField;
private Button tellSelectGetValue;
public MainView ( )
{
yearField = new IntegerField( "Filter years before: " );
yearField.addValueChangeListener(
( AbstractField.ComponentValueChangeEvent < IntegerField, Integer > event ) -> {
Integer year = event.getValue();
// If the user cleared the field, its value is null. In such a case, clear all filters.
// If the user entered a year number into this field, specify a filter.
if ( Objects.isNull( year ) )
{
( ( ListDataProvider < LocalDate > ) grid.getDataProvider() ).clearFilters();
} else
{
( ( ListDataProvider < LocalDate > ) grid.getDataProvider() ).setFilter( ( LocalDate localDate ) -> localDate.getYear() < year );
}
}
);
tellSelectGetValue = new Button( "SingleSelect.getValue()" );
tellSelectGetValue.addClickListener(
( ClickEvent < Button > clickEvent ) -> {
Notification.show( "grid.asSingleSelect().getValue() is " + grid.asSingleSelect().getValue() );
}
);
grid = new Grid <>();
List < LocalDate > dates = List.of(
LocalDate.of( 2020 , Month.JANUARY , 23 ) ,
LocalDate.of( 2019 , Month.FEBRUARY , 24 ) ,
LocalDate.of( 2022 , Month.MARCH , 25 ) ,
LocalDate.of( 2011 , Month.APRIL , 26 )
);
grid.setItems( new ArrayList < LocalDate >( dates ) );
grid.addColumn( LocalDate :: toString );
grid.addColumn( LocalDate :: getYear );
grid.addColumn( LocalDate :: getDayOfWeek );
this.add( yearField , tellSelectGetValue , grid );
}
}
Перед фильтрацией по году:
После фильтрации выбранного года SingleSelect
продолжает сообщать о нем как о выбранном , Обратите внимание на уведомление, отображаемое в правом нижнем углу, в результате нажатия кнопки.