Browse Source

Introduce Binder.addFialdValueChangeListener (#8273)

Fixes #8273
tags/8.0.0.beta2
Denis 7 years ago
parent
commit
38b4753308

+ 28
- 0
server/src/main/java/com/vaadin/data/Binder.java View File

@@ -39,6 +39,7 @@ import java.util.stream.Stream;
import com.googlecode.gentyref.GenericTypeReflector;
import com.vaadin.annotations.PropertyId;
import com.vaadin.data.HasValue.ValueChangeEvent;
import com.vaadin.data.HasValue.ValueChangeListener;
import com.vaadin.data.converter.StringToIntegerConverter;
import com.vaadin.data.validator.BeanValidator;
import com.vaadin.event.EventRouter;
@@ -928,6 +929,7 @@ public class Binder<BEAN> implements Serializable {
binderValidationResults);
getBinder().getValidationStatusHandler().statusChange(status);
getBinder().fireStatusChangeEvent(status.hasErrors());
getBinder().fireValueChangeEvent(event);
}

/**
@@ -1734,6 +1736,29 @@ public class Binder<BEAN> implements Serializable {
StatusChangeListener.class.getDeclaredMethods()[0]);
}

/**
* Adds field value change listener to all the fields in the binder.
* <p>
* Added listener is notified every time whenever any bound field value is
* changed. The same functionality can be achieved by adding a
* {@link ValueChangeListener} to all fields in the {@link Binder}.
* <p>
* The listener is added to all fields regardless of whether the method is
* invoked before or after field is bound.
*
* @see ValueChangeEvent
* @see ValueChangeListener
*
* @param listener
* a field value change listener
* @return a registration for the listener
*/
public Registration addValueChangeListener(
ValueChangeListener<?> listener) {
return getEventRouter().addListener(ValueChangeEvent.class, listener,
ValueChangeListener.class.getDeclaredMethods()[0]);
}

/**
* Creates a new binding with the given field.
*
@@ -2239,4 +2264,7 @@ public class Binder<BEAN> implements Serializable {
return fieldName.toLowerCase(Locale.ENGLISH).replace("_", "");
}

private <V> void fireValueChangeEvent(ValueChangeEvent<V> event) {
getEventRouter().fireEvent(event);
}
}

+ 167
- 0
server/src/test/java/com/vaadin/data/BinderValueChangeTest.java View File

@@ -0,0 +1,167 @@
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.data;

import java.util.concurrent.atomic.AtomicReference;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import com.vaadin.data.Binder.BindingBuilder;
import com.vaadin.data.HasValue.ValueChangeEvent;
import com.vaadin.data.converter.StringToIntegerConverter;
import com.vaadin.tests.data.bean.Person;
import com.vaadin.ui.TextField;

/**
* @author Vaadin Ltd
*
*/
public class BinderValueChangeTest
extends BinderTestBase<Binder<Person>, Person> {

private AtomicReference<ValueChangeEvent<?>> event;

private static class TestTextField extends TextField {
@Override
protected boolean setValue(String value, boolean userOriginated) {
return super.setValue(value, userOriginated);
}
}

@Before
public void setUp() {
binder = new Binder<>();
item = new Person();
event = new AtomicReference<>();
}

@Test
public void unboundField_noEvents() {
binder.addValueChangeListener(this::statusChanged);

BindingBuilder<Person, String> binding = binder.forField(nameField);

nameField.setValue("");
Assert.assertNull(event.get());

binding.bind(Person::getFirstName, Person::setFirstName);
Assert.assertNull(event.get());
}

@Test
public void setBean_unbound_noEvents() {
binder.addValueChangeListener(this::statusChanged);

Assert.assertNull(event.get());

binder.setBean(item);

Assert.assertNull(event.get());
}

@Test
public void readBean_unbound_noEvents() {
binder.addValueChangeListener(this::statusChanged);

Assert.assertNull(event.get());

binder.readBean(item);

Assert.assertNull(event.get());
}

@Test
public void setValue_unbound_singleEventOnSetValue() {
binder.forField(nameField).bind(Person::getFirstName,
Person::setFirstName);
binder.forField(ageField)
.withConverter(new StringToIntegerConverter(""))
.bind(Person::getAge, Person::setAge);

binder.addValueChangeListener(this::statusChanged);

Assert.assertNull(event.get());
nameField.setValue("foo");
verifyEvent(nameField);
}

@Test
public void setValue_bound_singleEventOnSetValue() {
binder.forField(nameField).bind(Person::getFirstName,
Person::setFirstName);
binder.forField(ageField)
.withConverter(new StringToIntegerConverter(""))
.bind(Person::getAge, Person::setAge);
binder.setBean(item);

binder.addValueChangeListener(this::statusChanged);

Assert.assertNull(event.get());
nameField.setValue("foo");
verifyEvent(nameField);
}

@Test
public void userOriginatedUpdate_unbound_singleEventOnSetValue() {
TestTextField field = new TestTextField();

binder.forField(field).bind(Person::getFirstName, Person::setFirstName);
binder.forField(ageField)
.withConverter(new StringToIntegerConverter(""))
.bind(Person::getAge, Person::setAge);

binder.addValueChangeListener(this::statusChanged);

Assert.assertNull(event.get());
field.setValue("foo", true);
verifyEvent(field, true);
}

@Test
public void addListenerFirst_bound_singleEventOnSetValue() {
binder.addValueChangeListener(this::statusChanged);

binder.forField(nameField).bind(Person::getFirstName,
Person::setFirstName);
binder.forField(ageField)
.withConverter(new StringToIntegerConverter(""))
.bind(Person::getAge, Person::setAge);
binder.setBean(item);

Assert.assertNull(event.get());
ageField.setValue(String.valueOf(1));
verifyEvent(ageField);
}

private void verifyEvent(HasValue<?> field) {
verifyEvent(field, false);
}

private void verifyEvent(HasValue<?> field, boolean isUserOriginated) {
ValueChangeEvent<?> changeEvent = event.get();
Assert.assertNotNull(changeEvent);
Assert.assertEquals(field, changeEvent.getSource());
Assert.assertEquals(field, changeEvent.getComponent());
Assert.assertEquals(isUserOriginated, changeEvent.isUserOriginated());
}

private void statusChanged(ValueChangeEvent<?> evt) {
Assert.assertNull(event.get());
event.set(evt);
}
}

Loading…
Cancel
Save