SingleSelect по-прежнему содержит выбранный элемент, несмотря на то, что этот элемент отфильтровывается от отображения в сетке (Ваадин 14) - PullRequest
1 голос
/ 17 февраля 2020

Когда пользователь выбирает элемент 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 );
    }
}

Перед фильтрацией по году:

screenshot before filtering

После фильтрации выбранного года SingleSelect продолжает сообщать о нем как о выбранном , Обратите внимание на уведомление, отображаемое в правом нижнем углу, в результате нажатия кнопки.

screenshot after filtering

1 Ответ

0 голосов
/ 06 марта 2020

Полностью согласен с комментарием Эрика Люмма:

Сетка не может знать, находится ли выбранный элемент в наборе данных, без извлечения всех строк. Для ListDataProvider выбор всех строк не является проблемой, но в общем случае, когда поставщик данных может загружаться или не загружаться лениво, выбор всех элементов не возможен.

Кроме того, я бы не стал Не советуем использовать DataProviderListener для обновления деталей вашего товара. ИМО сетка addSelectionListener больше подходит. Он будет срабатывать каждый раз, когда выбор в сетке изменяется, даже если он изменен кодом (но может быть различен методом isFromClient). Однако вам нужно будет явно очистить выделение в сетке, когда фильтр меняется и предыдущий выбранный элемент не совпадает.

...