vaadin / flow-components

Java counterpart of Vaadin Web Components
100 stars 66 forks source link

Filtering grid causes Got an RPC for non-existent node warning #1157

Closed kuvalda07 closed 2 years ago

kuvalda07 commented 4 years ago

Filtering grid with component-columns causes a Got an RPC for non-existent node warning. When adding a button as a component of a column, it's OK. But using, for example, Checkbox, TextField, TextArea causes a warning while filtering via TextField filter. One common thing, that they implement HasValue.

Vaadin: 14.1.18. OS: Windows 7. Browser: Firefox 73.0.1.

Sample code is attached below.

@Route public class MainView extends VerticalLayout { private static final long serialVersionUID = 1L;

public MainView() {
    super();

    Collection<Integer> items = new ArrayList<>();
    Random r = new Random();
    IntStream.rangeClosed(1, 100).forEach(i -> items.add(r.nextInt()));
    ListDataProvider<Integer> dataProvider = new ListDataProvider<>(items);
    Grid<Integer> grid = new Grid<>();
    grid.setDataProvider(dataProvider);

    Column<Integer> idColumn = grid.addColumn(Integer::intValue).setHeader("id");

    grid.addColumn(new ComponentRenderer<>(item -> new Button("Button"))); // Button is OK

    grid.addColumn(new ComponentRenderer<>(item -> new Checkbox("Checkbox"))); // [WARN] Got an RPC for non-existent
                                                                                // node
    grid.addColumn(new ComponentRenderer<>(item -> new TextField("TextField"))); // [WARN] Got an RPC for
                                                                                    // non-existent node
    grid.addColumn(new ComponentRenderer<>(item -> new TextArea("TextArea"))); // [WARN] Got an RPC for non-existent
                                                                                // node

    HeaderRow filterRow = grid.appendHeaderRow();
    TextField idField = new TextField();
    idField.addValueChangeListener(event -> dataProvider
            .addFilter(item -> StringUtils.containsIgnoreCase(item.toString(), idField.getValue())));
    idField.setValueChangeMode(ValueChangeMode.EAGER);
    idField.setSizeFull();
    filterRow.getCell(idColumn).setComponent(idField);

    grid.setSizeFull();
    add(idField, grid);

    setSizeFull();
}

}

TatuLund commented 2 years ago

This logging in frequent in many harmless cases. Find below another one.

I think it happens because refreshAll will cause component (this case component in Grid cell) to be detached in the middle of the value change event handling. So something is received by server after detach and thus warning logged. Here you could just ignore this. I am just thinking, that log level could be info or debug for this.

public class GridTest extends Div {
    public class Item {
        private Integer quantity;
        public Integer getQuantity() { return quantity; }
        public void setQuantity(Integer quantita) { this.quantity = quantita; }

        public Item(Integer q) {
            quantity = q;
        }
    }

    public GridTest() {
        Grid<Item> shoppingCartGrid = new Grid<>(Item.class);
        ListDataProvider<Item> dp = new ListDataProvider<>(Arrays.asList(
            new Item(34),
            new Item(99),
            new Item(12)
        ));
        shoppingCartGrid.setDataProvider(dp);

        Grid.Column<Item> quantityColumn = shoppingCartGrid.addComponentColumn(item -> {
            IntegerField integerField = new IntegerField();
            integerField.addThemeVariants(TextFieldVariant.LUMO_ALIGN_CENTER);
            integerField.setHasControls(true);
            integerField.setValue(item.getQuantity());
            integerField.setMin(0);
            integerField.addValueChangeListener(e -> {
                item.setQuantity(e.getValue());
                dp.refreshAll();
            });
            return integerField;
        });

        add(shoppingCartGrid);

    }
}
TatuLund commented 2 years ago

And there is even more minimal way to reproduce the warning

        TextField field = new TextField();
        field.addValueChangeListener(event -> {
            remove(field);
        });