reactjs/react-future

API for managing selection state

sophiebits opened this issue · 4 comments

Managing the selection with something like a filtered controlled <input> is a huge pain right now -- if you do the simple thing of filtering the value in the onChange handler

handleChange: function(e) {
  this.setState({text: e.target.value.replace(/^[0-9]/g, '')});
},

then your cursor jumps to the end of the text box when typing non-digit characters anywhere into the field.

For comparison, Elm treats the selection state as part of an input's value.

Did you solve this?

@spicyj I was also wondering if you'd had any further movement on this. I'm actually just getting it in my normal controlled inpet when typing at a speed over 40 wpm (I happend to have a lot of other stuff going on at the same time in my app).

None currently. If you have good ideas we'd love to hear them.

I did a lot of experiments on this a year or so ago. It's not terribly complex but the API becomes rather cumbersome or inflexible with if done naively:

A. Always only mutate text left/right/inside of selection, works as-is.
B. Selection as a property, {text: '', selection: [0, 1]}.
C. Text left/right/inside of selection as a property, {left: '', right: '', selected: ''}.

Problem is that only A is self-contained, but it does not behave (strictly) as intended if the value of the input is replaced entirely and is rather inflexible. The other 2 are actually incomplete. So what's really needed is probably a (somewhat) opaque type, provide a bunch of helpers for mutating it.

Something like this perhaps:

var FooBar = React.createClass({
  getInitialState() {
    return {
      inputValue: createSuperInputValue({
        value: '',
        onChange: function(value) {}
      })
    }
  },
  mutateInput() {
    this.setState({
      inputValue: fooBarMutateSuperInputValue(this.state.inputValue, ...)
    });
  },
  render() {
    return (
      <SuperInput
        value={this.props.inputValue}
        onChange={newValue => this.setState({inputValue: newValue})}
      />
    );
  }
});

However, regardless of what the solution is. Know that in most browsers you end up discarding the undo history, in Chrome you actually end up corrupting it so undoing ruins what you wrote. So my current recommendation is to just stick with text-transform and preventDefault in onKeyPress.