Vaadin Grid doesn't get refreshed on event

Viewed 126

I have the following component and my grid doesn't get refreshed when I receive a Spring event. Why is that?

@Component
@Scope(SCOPE_PROTOTYPE)
public class SearchResultGridView extends Grid<SearchResultModel> implements
        ApplicationListener<FetchBySubscriptionNumberAction> {

    private static final Logger log = LoggerFactory.getLogger(SearchView.class);

    private final SumoCmMemberService sumoCmMemberService;
    private List<SearchResultModel> searchResultModels = new ArrayList<>();

    private final List<String> columnNames = List.of(
            "subscriptionNumber",
            "mnr",
            "firstName",
            "lastName",
            "dateOfBirth",
            "street",
            "houseNumber",
            "box",
            "postalCode",
            "locality",
            "active"
    );

    public SearchResultGridView(SumoCmMemberService sumoCmMemberService) {
        super(SearchResultModel.class, false);

        this.sumoCmMemberService = sumoCmMemberService;

        initGridColumns();
        initStyle();
    }

    private void initGridColumns() {
        columnNames.forEach(columnName -> addColumn(columnName).setAutoWidth(true));
    }

    private void initStyle() {
        addThemeVariants(GridVariant.LUMO_NO_BORDER);
        setHeightFull();
    }


    @Override
    public void onApplicationEvent(FetchBySubscriptionNumberAction action) {
        log.info(action.getSubscriptionNumber());
        sumoCmMemberService
                .fetchBySubscriptionNumber(action.getSubscriptionNumber())
                .doOnError(e -> log.error("error in webflux: " + e.getMessage()))
                .subscribe(sumoCmMemberDto -> {
                    SumoSubscriptionDto sumoSubscriptionDto = sumoCmMemberDto.getSumoSubscription();
                    SearchResultModel searchResultModel = SearchResultModel
                            .builder()
                            .mnr(sumoCmMemberDto.getMnumber())
                            .firstName(sumoSubscriptionDto.getFirstName())
                            .lastName(sumoSubscriptionDto.getLastName())
                            .street(sumoSubscriptionDto.getStreet())
                            .houseNumber(sumoSubscriptionDto.getHouseNumber())
                            .box(sumoSubscriptionDto.getBox())
                            .active(sumoCmMemberDto.isActive())
                            .build();
                    searchResultModels = List.of(searchResultModel);
                    setItems(searchResultModels);
                });
    }

}

I'm using a Mono from a service from which I subscribe, and I simply want to replace the items.

Note: I dislike the DataProvider api, and I wish not to use it.
My use case is simple; I want to subscribe to a Mono reactive stream and refresh the table.
So why doesn't this work? The simplest use case of the Grid Layout api makes believe that it should. No compiler errors and no runtime errors. Just nothing happens, and the grid doesn't display the data I provide to it. In debug modus, I see that the list is properly populated.

enter image description here

But the grid, nothing displays.

1 Answers

The problem is that there is no ongoing client request, so there is no way for Vaadin to let the browser know something has changed.

What you need to do is to configure @Push to enable two-way communication and then use ui.access() to handle the update:

UI ui = UI.getCurrent();
[...]
.subscribe(sumoCmMemberDto -> {
                    SumoSubscriptionDto sumoSubscriptionDto = sumoCmMemberDto.getSumoSubscription();
                    SearchResultModel searchResultModel = SearchResultModel
                            .builder()
                            .mnr(sumoCmMemberDto.getMnumber())
                            .firstName(sumoSubscriptionDto.getFirstName())
                            .lastName(sumoSubscriptionDto.getLastName())
                            .street(sumoSubscriptionDto.getStreet())
                            .houseNumber(sumoSubscriptionDto.getHouseNumber())
                            .box(sumoSubscriptionDto.getBox())
                            .active(sumoCmMemberDto.isActive())
                            .build();
                    searchResultModels = List.of(searchResultModel);
                    ui.access(()->setItems(searchResultModels)); // wrap setItems in ui.access()
                });

Read more here in the docs: https://vaadin.com/docs/latest/flow/advanced/server-push/#push.access (there are small differences in V14 vs latest, so make sure you read docs for the correct version)

Related