Skip to content

Commit

Permalink
#339 fixed, hopefully
Browse files Browse the repository at this point in the history
digit changes should no longer be destructive
  • Loading branch information
vaadin-miki committed Jan 11, 2022
1 parent b736a24 commit 4eeea5c
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import com.vaadin.flow.component.BlurNotifier;
import com.vaadin.flow.component.Component;
import com.vaadin.flow.component.FocusNotifier;
import com.vaadin.flow.component.HasValue;
import com.vaadin.flow.component.customfield.CustomField;
import com.vaadin.flow.component.dependency.CssImport;
import com.vaadin.flow.component.textfield.HasPrefixAndSuffix;
Expand Down Expand Up @@ -39,6 +40,7 @@
import java.text.ParseException;
import java.util.Locale;
import java.util.Optional;
import java.util.function.Consumer;

/**
* Base class for super number fields.
Expand Down Expand Up @@ -128,6 +130,8 @@ public abstract class AbstractSuperNumberField<T extends Number, SELF extends Ab

private boolean focused = false;

private Registration innerFieldValueChangeRegistration;

/**
* Creates the field.
* @param defaultValue Default value to use on startup and when there are errors.
Expand Down Expand Up @@ -163,9 +167,32 @@ protected AbstractSuperNumberField(T defaultValue, SerializablePredicate<T> nega
this.field.addBlurListener(this::onFieldBlurred);
this.field.addTextSelectionListener(this::onTextSelected);
// the following line allows for ValueChangeMode to be effective (#337)
// at the same time, it makes setting fraction/integer digits destructive
// at the same time, it makes setting fraction/integer digits destructive (see #339)
// (because without it the value would be updated on blur, and not on every change)
this.field.addValueChangeListener(event -> this.updateValue());
this.listenToValueChangesFromInnerField();
}

private void listenToValueChangesFromInnerField() {
if(this.innerFieldValueChangeRegistration == null)
this.innerFieldValueChangeRegistration = this.field.addValueChangeListener(this::onFieldChanged);
}

/**
* Runs the given consumer and ignores any value change effects that happen during that time.
* @param consumer An action to perform. Will receive {@code this} as a parameter.
*/
private void ignoreValueChangesFromInnerField(Consumer<AbstractSuperNumberField<T, SELF>> consumer) {
final boolean restore = this.innerFieldValueChangeRegistration != null;
if(restore)
this.innerFieldValueChangeRegistration.remove();
this.innerFieldValueChangeRegistration = null;
consumer.accept(this);
if(restore)
this.listenToValueChangesFromInnerField();
}

private void onFieldChanged(HasValue.ValueChangeEvent<String> event) {
this.updateValue();
}

/**
Expand Down Expand Up @@ -247,7 +274,7 @@ protected void setIntegerPartOptional(boolean optional) {
*/
protected void setMinimumFractionDigits(int digits) {
this.format.setMinimumFractionDigits(digits);
this.updateRegularExpression();
this.updateRegularExpression(true);
}

/**
Expand All @@ -258,7 +285,7 @@ protected void setMinimumFractionDigits(int digits) {
*/
protected void setMaximumFractionDigits(int digits) {
this.format.setMaximumFractionDigits(digits);
this.updateRegularExpression();
this.updateRegularExpression(true);
}

/**
Expand All @@ -269,7 +296,7 @@ protected void setMaximumFractionDigits(int digits) {
*/
public void setMaximumIntegerDigits(int digits) {
this.format.setMaximumIntegerDigits(digits);
this.updateRegularExpression();
this.updateRegularExpression(true);
}

/**
Expand All @@ -284,6 +311,18 @@ public final SELF withMaximumIntegerDigits(int digits) {
return (SELF)this;
}

/**
* Builds the regular expression and optionally ignores value change events from the underlying field.
* Basically allows the representation of the value to be changed, but not the value itself.
* @param ignoreValueChangeFromField Whether to ignore value change events coming from the underlying field.
*/
protected final void updateRegularExpression(boolean ignoreValueChangeFromField) {
// hopefully fixes #339
if(ignoreValueChangeFromField)
this.ignoreValueChangesFromInnerField(AbstractSuperNumberField::updateRegularExpression);
else this.updateRegularExpression();
}

/**
* Builds the regular expression for matching the input.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,18 @@ public void testMinimumFractionDigits() {
this.getField().setValue(TEN_DIGITS_PLUS_TWO);
this.getField().setMinimumFractionDigits(6);
Assert.assertEquals(FORMATTED_TEN_DIGITS_PLUS_TWO+"0000", this.getField().getRawValue());
Assert.assertEquals(new BigDecimal("1234567890.120000"), this.getField().getValue());
Assert.assertEquals(TEN_DIGITS_PLUS_TWO, this.getField().getValue());
}

@Test
public void testMaximumFractionDigits() {
this.getField().setValue(TEN_DIGITS_PLUS_TWO);
this.getField().setMaximumFractionDigits(1);
Assert.assertEquals("1 234 567 890,1", this.getField().getRawValue());
Assert.assertEquals(new BigDecimal("1234567890.1"), this.getField().getValue());
Assert.assertEquals(TEN_DIGITS_PLUS_TWO, this.getField().getValue());
this.getField().setMaximumFractionDigits(2);
Assert.assertEquals(FORMATTED_TEN_DIGITS_PLUS_TWO, this.getField().getRawValue());
Assert.assertEquals(TEN_DIGITS_PLUS_TWO, this.getField().getValue());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public void testMaximumFractionDigits() {
this.getField().setValue(1.234d);
this.getField().setMaximumFractionDigits(1);
Assert.assertEquals("1,2", this.getField().getRawValue());
Assert.assertEquals(1.2, this.getField().getValue(), 0);
Assert.assertEquals(1.234d, this.getField().getValue(), 0);
}

}

0 comments on commit 4eeea5c

Please sign in to comment.