ValueChangeListener over-eager on table?

Hi,

I have a BeanItemContainer-backed Table and a field with a ValueChangeListener attached. For some reason the VCL fires when the table is first rendered? Is this normal and what would be the standard way of working around this (apart from distict boolean flagging in the view)?

It could also be noted that sorting the table also fires the trigger…

Thanks in advance,
Nik

Is there any reliable way of detecting the case where a user really changes the values and e.g. tabs out?

I didn’t see any indication in the documentation that this is the intended behavior(?). It feels a bit conter-intuative if you have a table in edit mode that renders 100+ rows with text fields triggering value change events when the table is rendered (not to mention incorrect if the change is timestamped in a DB etc)…

“Any help you could give would be, uh, very, uh . . . helpful”

Can you please post some code on how you initialize the table and the field with the listener?

Even the most simple example I can think of echoes the “!” on initial render

        Table t = new Table();
        t.addContainerProperty("Foo", String.class, null);
        t.addItem("foo");
        t.setEditable(true);
        t.setTableFieldFactory(new TableFieldFactory() {

            @Override
            public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) {
                TextField f = new TextField();
                f.addValueChangeListener(e -> {
                    System.out.println("!");
                });
                return f;
            }
        });

Hi Nicklas,
the listener is invoked because the datasource for the field is set after the listener is registered.

Try manually setting the datasource before registering the listener

        t.setTableFieldFactory(new TableFieldFactory() {

            @Override
            public Field<?> createField(Container container, Object itemId, Object propertyId, Component uiContext) {
                TextField f = new TextField();
                f.setPropertyDataSource(container.getContainerProperty(itemId, propertyId));
                f.addValueChangeListener(e -> {
                    System.out.println("!");
                });
                return f;
            }
        });

HTH
Marco

That did the trick! Thanks!

It’s a bit confusing since it sort of works with the auto-wiring. If the factory-generated field would not bind at all it would have been easier to track down

BTW this is a workaround; after field creation TextField.setPropertyDataSource is invoked again by Table.
bindPropertyToField but now old value and new value are the same so the change event is not fired.

Best regards
Marco

Just a note that Vaadin 8 event handling should make situations like this simpler to handle; stay tuned :wink:

-Olli

For anyone stumbling onto this it might be worth nothing that any converters should also be set before the VCL is registered…