setPropertyDataSource's formatter does not work for custom component

Hello,

I’m working on a Vaadin 6 project and I have implemented a new custom component (that extends CustomComponent and implements Field). The custom component has a textfield (the actual ‘bound’ field) and a label (for information next to the textfield). The problem arrives when I call setPropertyDataSource with a specific decimal formatter. It just ignores the formatting. If I just call the same method on a plain textfield, then I get the formatting I want. Here’s my custom component:

CustomComponent implementation class:

public class TextFieldWithCalculatedLabelCustomComponent extends CustomComponent implements Field {
    private TextField boundField = new TextField();
    private Label label = new Label();

    public TextFieldWithCalculatedLabelCustomComponent(final GtmxAttrbts gtmxAttrbts, String labelCaption) {
        HorizontalLayout layout = new HorizontalLayout();
        layout.setSpacing(true);
        layout.addComponent(boundField);
        boundField.setImmediate(true);
        boundField.setNullRepresentation("");
        boundField.setNullSettingAllowed(true);

        label.setCaption(labelCaption);
        
        layout.addComponent(label);
        layout.setComponentAlignment(label, "b");
        setCompositionRoot(layout);
    }

    public abstract void calculateLabel();
    
    public TextField getBoundField() {
        return boundField;
    }

    public Label getLabel() {
        return label;
    }

    public String getRequiredError() {
        return boundField.getRequiredError();
    }

    public boolean isRequired() {
        return boundField.isRequired();
    }

    public void setRequired(boolean required) {
        boundField.setRequired(required);
    }

    public void setReadOnly(boolean readOnly) {
        boundField.setReadOnly(readOnly);
    }

    public boolean isReadOnly() {
        return boundField.isReadOnly();
    }

    public void setRequiredError(String requiredMessage) {
        boundField.setRequiredError(requiredMessage);
    }

    public boolean isInvalidCommitted() {
        return boundField.isInvalidCommitted();
    }

    public void setInvalidCommitted(boolean isCommitted) {
        boundField.setInvalidCommitted(isCommitted);

    }

    public void commit() throws SourceException, InvalidValueException {
        boundField.commit();
    }

    public void discard() throws SourceException {
        boundField.discard();

    }

    public boolean isModified() {
        return boundField.isModified();
    }

    public boolean isReadThrough() {
        return boundField.isReadThrough();
    }

    public boolean isWriteThrough() {

        return boundField.isWriteThrough();
    }

    public void setReadThrough(boolean readThrough) throws SourceException {
        boundField.setReadThrough(readThrough);

    }

    public void setWriteThrough(boolean writeThrough) throws SourceException, InvalidValueException {
        boundField.setWriteThrough(writeThrough);

    }

    public void addValidator(Validator validator) {
        boundField.addValidator(validator);

    }

    public Collection<Validator> getValidators() {

        return boundField.getValidators();
    }

    public boolean isInvalidAllowed() {
        return boundField.isInvalidAllowed();
    }

    public boolean isValid() {
        return boundField.isValid();
    }

    public void removeValidator(Validator validator) {
        boundField.removeValidator(validator);

    }

    public void setInvalidAllowed(boolean invalidValueAllowed) throws UnsupportedOperationException {
        boundField.setInvalidAllowed(invalidValueAllowed);

    }

    public void validate() throws InvalidValueException {
        boundField.validate();
    }

    public Class<?> getType() {
        return boundField.getType();
    }

    public void setValue(Object newValue) throws ReadOnlyException, ConversionException {
        boundField.setValue(newValue);

    }

    public void addListener(ValueChangeListener listener) {
        boundField.addListener(listener);

    }

    public void removeListener(ValueChangeListener listener) {
        boundField.removeListener(listener);

    }

    public void valueChange(com.vaadin.data.Property.ValueChangeEvent event) {
        boundField.valueChange(event);

    }

    public Property getPropertyDataSource() {
        return boundField.getPropertyDataSource();
    }

    public void setPropertyDataSource(Property newDataSource) {
        boundField.setPropertyDataSource(newDataSource);

    }

    public void focus() {
        boundField.focus();
    }

    public int getTabIndex() {
        return boundField.getTabIndex();

    }

    public void setTabIndex(int tabIndex) {
        boundField.setTabIndex(tabIndex);

    }

    public Object getValue() {
        return boundField.getValue();
    }
}

Using the custom component:

Field f = new TextFieldWithCalculatedLabelCustomComponent(gtmxAttrbts, "my label caption"); f.setPropertyDataSource(new BigDecimalFormatter(f.getPropertyDataSource())); The formatter itself (just in case it’s important):

public class BigDecimalFormatter extends PropertyFormatter {

    public BigDecimalFormatter(Property propertyDataSource) {
        super();
        this.setPropertyDataSource(propertyDataSource);
    }

    @Override
    public Object parse(String formattedValue) throws Exception {
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN);
        DecimalFormat df = (DecimalFormat) nf;
        df.applyPattern("###,###.#####");

        Number d = df.parse(formattedValue);
        return new BigDecimal(d.doubleValue());
    }

    @Override
    public String format(Object value) {
        NumberFormat nf = NumberFormat.getNumberInstance(Locale.GERMAN);
        DecimalFormat df = (DecimalFormat) nf;
        df.applyPattern("###,###.#####");

        return df.format(((BigDecimal) value).doubleValue());
    }
}

See the difference using the same formatter for a plain Textfield vs Custom Component:


The plain Textfield respects the decimal delimiter being a comma. The custom component does not want the comma as a decimal delimiter :slight_smile:

Any ideas? Thanks in advance.

Regards,

Jim