gcanti / tcomb-form

Forms library for react
https://gcanti.github.io/tcomb-form
MIT License
1.16k stars 136 forks source link

Allowing input to be either t.String or t.Number #237

Closed VinSpee closed 8 years ago

VinSpee commented 8 years ago

Hi!

I'm working on an input as such:

Given an input, a min, and a max, remove all non-digits and make sure the resulting value is between the min and max.

TEST 1: INPUT = 10000; OUTPUT = true

TEST 2: INPUT = '$10,000'; OUTPUT = true

export default (min = 0, max = Infinity) => {
  return t.refinement(t.String, (amount) => {
    const amountValue = parseInt(amount.replace(/[^\d]/g, ''));
    return (amountValue >= min) && (amountValue <= max)
  });
};

Currently, TEST 1 does not work because the inputted value is treated as a number and not t.String. How can I make this input accept either a string or number?

gcanti commented 8 years ago

Not sure I'm follow.

If you want a string as output, this works for me:

const createInput = (min = 0, max = Infinity) => {
  return t.refinement(t.String, (amount) => {
    const amountValue = parseInt(amount.replace(/[^\d]/g, ''));
    return (amountValue >= min) && (amountValue <= max);
  });
};

const Type = t.struct({
  x: createInput(1, 4)
});

const App = React.createClass({

  onSubmit(evt) {
    evt.preventDefault();
    var value = this.refs.form.getValue();
    if (value) {
      console.log(value);
    }
  },

  render() {
    return (
      <form onSubmit={this.onSubmit}>
        <t.form.Form
          ref="form"
          type={Type}
        />
        <div className="form-group">
          <button type="submit" className="btn btn-primary">Save</button>
        </div>
      </form>
    );
  }

});

otherwise if you want a number as output you can simply use a refinement of a t.Number:

const createInput = (min = 0, max = Infinity) => {
  return t.refinement(t.Number, (amount) => {
    return (amount >= min) && (amount <= max);
  });
};

const Type = t.struct({
  x: createInput(1, 4)
});
VinSpee commented 8 years ago

in the first case, if the input is a number, the form will throw a validation error. I want to handle the inputs $10,000 and 10000 the same way.

gcanti commented 8 years ago

in the first case, if the input is a number...

How could the user input be a number? The value of a textbox is always a string.

VinSpee commented 8 years ago

ahh I figured it out - this may be a bug.

I assigned state.value with some mock data. the mock data had that input's value as an int.