Search code examples
reactjsnormalizationredux-form

Redux-Form separating displayed value and submitted value in custom component


I have a custom component CurrencyBox and I use redux-form to submit and validate form. It works perfectly for entered inputs like "123,345", "1.000.000", or "9.000,123" etc.

Today, I need to send input value (1.000.000,456) to server as (1000000,456).

In short, displayed value must be like 123.456,789 but submitted value must be 123456,789

Is there anyway to handle this?

I checked normalizers etc. but these are not feasible solutions for me. I just want to separate displayed value and submitted value.

Regards.


Solution

  • You need to create a wrapper component for the input component, for example TextField, this component should receive the mask and the actual value, you will need to setup a few handlers for onChange, onFocus and any other callback that you need, for example:

    const { string, func } = PropTypes;
    
    class TextField extends Component {
      static propTypes = {
        value: string,
        onChange: func,
        format: string,
      };
    
      getFormat(value) {
        // set the format that you need
        // based on the format prop or any other option
        return applyFormat(value);
      }
    
      handleChange = (event) => {
        const value = event.target.value;
        const { onChange } = this.props;
    
        if (onChange) {
          // Before returning the value
          // you need to remove the format
          onChange(removeFormat(value));
        }
      }
    
      render() {
        const { value } = this.props;
    
        return (
          <input
            type="text"
            value={this.getFormat(value)}
            onChange={this.handleChange}
          />
        );
      }
    }
    

    This is a very simple example of what you could do, basically before rendering the value you set the format and on the onChange you need to remove the format, you could implement the onBlur instead of the onChange, this way if you are using redux the data will be send to your reducer until the user completes the editing, preventing calling the reducer on every keystroke.

    Usage:

    <TextField
     value={this.props.dataFromRedux}
     onChange={this.props.actionCreatorToSaveValueOnState}
    />
    

    I hope this helps!