Vaadin Grid: Cannot read property 'length' of undefined in grid.$connector.

Hey there :slight_smile:

We’re setting up a grid where the user is able to filter items which are related to brands.
One filter parameter is selecting a brand via a combobox, the other is typing in chars of the title of items.
The view is a PolymerTemplate.

What we got so far is:

//Fetch grid from client: remember, children are not populated to server side
@Id("grid")
private Grid<SearchItem> grid;
private DataProvider<SearchItem, SearchItemParams> searchItemDataProvider;
private ConfigurableFilterDataProvider<SearchItem, Void, SearchItemParams> searchItemWrapper;

this.searchItemDataProvider = DataProvider.fromFilteringCallbacks(query -> {
	SearchItemParams filter = query.getFilter().orElse(null);
	if(filter == null) {
		filter = new SearchItemParams(null, null);
	}

	final Flux<SearchItem> items = this.itemStorageWebClient.post().uri(this.itemServiceSearchEndpoint)
			.accept(MediaType.APPLICATION_STREAM_JSON)
			.contentType(MediaType.APPLICATION_STREAM_JSON)
			.body(BodyInserters.fromPublisher(Mono.just(filter), SearchItemParams.class))
			.exchange()
			.log()
			.flatMapMany(clientResponse -> clientResponse.bodyToFlux(SearchItem.class));
	return items.log().toStream();

}, query -> {
    //@todo add endpoint + x-total-count header for getting number of items
	SearchItemParams filter = query.getFilter().orElse(null);
	if(filter == null) {
		filter = new SearchItemParams(null, null);
	}

	final Flux<SearchItem> items = this.itemStorageWebClient.post().uri(this.itemServiceSearchEndpoint)
			.accept(MediaType.APPLICATION_STREAM_JSON)
			.contentType(MediaType.APPLICATION_STREAM_JSON)
			.body(BodyInserters.fromPublisher(Mono.just(filter), SearchItemParams.class))
			.exchange()
			.log()
			.flatMapMany(clientResponse -> clientResponse.bodyToFlux(SearchItem.class));
	return items.count().log().block().intValue();
});

this.searchItemWrapper = this.searchItemDataProvider.withConfigurableFilter();
this.grid.setDataProvider(this.searchItemWrapper);
/*  
 * workaround to get data into the columns which are defined in the polymer html.
 * in polymer in the column templates, the data is available via "colx"
 */
//col0
this.grid.addColumn(SearchItem::getId);
//col1
this.grid.addColumn(SearchItem::getTitle);

SearchItem and SearchItemParams are just tiny pojo’s containing an id, a title and a brand.
As the page loads, the brand-combobox gets filled with all available brands.
When the user selects a brand

SearchItemParams params = new SearchItemParams(null, brand.getBrand());
this.searchItemWrapper.setFilter(params);

the filter got set.

At this point we’re facing the problem that in the client-side of the grid (in gridConnector.js on line 258)

let items = cache[page]
;
for (let j = 0; j < items.length; j++) {

item is undefined because somehow “page” is 1 (not 0 as expected) and the cache has the length 1. (See screenshot)
The item count of 2258 for the selected brand is correct also both flux (data + count).

If i select a brand which got less than 50 items, everything works as expected (page = 0).

Is this a bug? I hope my description of the problem is somehow comprehensible :smiley:

Btw: We are using flow beta 17 and grid 5.0.0

Thanks for your time :slight_smile:
17059294.png

Hi Martin,

You mentioned “workaround to get data into the columns which are defined in the polymer html.” in your source code. Can you share your template (or at least the relevant part of the template related to this issue)?

If you are defining the columns in the template, that might be the issue - when using Grid in a PolymerTemplate, configuring the columns via template is not supported yet (you have to use the Java API for that).

Hey Gilberto, thanks for your reply.

I just tried to create the grid on the server side:

this.grid = new Grid<SearchItem>();
this.grid.setDataProvider(this.searchItemWrapper);

this.grid.addColumn(SearchItem::getId);
this.grid.addColumn(SearchItem::getTitle);

this.placeholderDiv.add(this.grid);

but as soon as there are more than 50 items, the same errors show up again :-/

Here is a small example which is working with 50, but not more items, maybe its easier to recreate the error:

public class PortfolioTestView extends PolymerTemplate<TemplateModel> {
    public static final String ROUTE = "products/testportfolio/";

    private Grid<SearchItem> grid;
    private DataProvider<SearchItem, SearchItem> searchItemDataProvider;
    private ConfigurableFilterDataProvider<SearchItem, Void, SearchItem> searchItemWrapper;

    @Id("placeholder")
    private Div placeholder;

    private static class SearchItem {
        private String id;
        private String title;

        public SearchItem(String id, String title) {
            this.id = id;
            this.title = title;
        }

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }
    }


    @PostConstruct
    void testGrid() {

        List<SearchItem> searchitemlist = new ArrayList<>();

        for(int i = 0; i < 51; i++) {
            SearchItem si = new SearchItem(i + "", "item" + i);
            searchitemlist.add(si);
        }

        this.searchItemDataProvider = DataProvider.fromFilteringCallbacks(query -> {
            return searchitemlist.stream();

        }, query -> {
            return searchitemlist.size();
        });

        this.searchItemWrapper = this.searchItemDataProvider.withConfigurableFilter();

        this.grid = new Grid<SearchItem>();
        this.grid.setDataProvider(this.searchItemWrapper);

        this.grid.addColumn(SearchItem::getId).setHeader("Id");
        this.grid.addColumn(SearchItem::getTitle).setHeader("Title");

        this.placeholder.add(this.grid);
    }
}

Polymer:

<dom-module id="product-portfolio-test">
    <template>

        <div id="placeholder"></div>

    </template>
    <script>
        class ProductPortfolioTest extends Vaadin.ThemableMixin(Polymer.Element) {
            static get is() { return 'product-portfolio-test' }
            static get properties() {
                return {                };
            }
        }
        customElements.define(ProductPortfolioTest.is, ProductPortfolioTest);
    </script>
</dom-module>

Hi again Martin,

Thanks for the detailed description. It seems to be a bug in Grid. I’ve simplified the code even further and opened this ticket: https://github.com/vaadin/vaadin-grid-flow/issues/171 . Please take a look and add any other details you feel relevant.

Thank you!

Hi again,

After discussing with the team, we figured out what was the problem. If you use this code, then it works:

this.searchItemDataProvider = DataProvider.fromFilteringCallbacks(query -> {
            return searchitem.stream().skip(query.getOffset()).limit(query.getLimit());
        }, query -> {
            return searchitemlist.size();
        });

The thing is: the returned stream have to respect the limit returned by query.getLimit(). If it returns more items than intended, the crash occurs.

But your feedback raised a red flag - the exception on the client-side tells nothing about the nature of the actual error. We will improve on that.

Thanks again!

Thank you so much, everything is working now :slight_smile:
I think we misunderstood the documentation then.