Skip to content
This repository has been archived by the owner on Aug 23, 2022. It is now read-only.

Adding in formatter functionality #985

Merged
merged 2 commits into from
Oct 24, 2017
Merged

Conversation

brycesenz
Copy link
Contributor

This PR is meant to resolve #745.

Design

This functionality allows a function to be passed in as a formatter (in much the same way as parsers work). This formatter should expect as an input the form's model value, and is expected to transform that value into the way it should look on the input field.

As an example:

import React from 'react';
import PropTypes from 'prop-types';
import { Control, Errors } from 'react-redux-form';

const MonthYearInput = ({ name, ...rest }) => {
  // Converts a raw MMYY string into a more pretty "MM / YY" string
  const myFormatter = (val) => {
    const month = val.substring(0, 2);
    const year = val.substring(2, 4);
    return `${month} / ${year}`;
  };

  // Removes all of the non-numeric characters from "MM / YY", and limits the value to four chars
  const myParser = (val) => {
    const newVal = val.replace(/\D/g, '').substring(0, 4);
    return newVal;
  }

  return (
    <div className="input-wrapper">
      <Control.text
        model={name}
        parser={myParser}
        formatter={myFormatter}
      />
    </div>
  );
};

MonthYearInput.propTypes = {
  name: PropTypes.string.isRequired
};

MonthYearInput.defaultProps = {
};

export default MonthYearInput;

Pros

  • This approach gives the full control to the developer, and uses a very simple implementation
  • Easy to debug, as is it just a "hook" into the process of updating the modelValue from the viewValue

Cons

  • Potentially unintuitive at times. For example, if you wrote a formatter to append a dollar sign ($) to the front of a string, but didn't have a parser to strip it out of the model value, you would end up in a loop of continually appending dollar signs. E.g. three changes would give you $$$100.

I'm using this locally now, and find it really helpful. I'm open to any suggestions from @davidkpiano on how he would like this implemented though. I've also added some test specs to verify code correctness.

@davidkpiano davidkpiano merged commit e0949e8 into davidkpiano:master Oct 24, 2017
@greghawk
Copy link

@brycesenz I'm doing something very similar now myself via the change action. It is true that you have to marry a parser and formatter together. Perhaps if a formatter is a prop then a parser is required. Might fill the potential caveat.

@mikkelwf
Copy link

This is so nice.. :D

@valoricDe
Copy link
Contributor

Feedback for this merge:

  1. The Typescript-Types for formatter are missing.
  2. When the formatter adds charackters to the initial value the cursor jumps to the end of the input.

The second issue can be addressed by the user when he adds a onChange handler like:

({target} : ChangeEvent<any>) => {
        const {selectionStart} = target;
        setTimeout(() => {
          target.setSelectionRange(selectionStart + additionalAddedCharackters, selectionStart + additionalAddedCharackters);
        }, 0);
      };

@davidkpiano
Copy link
Owner

@Valorize Mind submitting a PR for the missing types? (And the second issue as well)

@valoricDe
Copy link
Contributor

@davidkpiano pr is created (#1087) The solution to the second issue is not perfect. It would be perfect to set the selectionRange after the input has been rendered. But I don't know where to hook into.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Formatters versus Parsers missing functionality
5 participants