react-future icon indicating copy to clipboard operation
react-future copied to clipboard

API for managing selection state

Open sophiebits opened this issue 10 years ago • 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.

sophiebits avatar May 07 '14 12:05 sophiebits

Did you solve this?

montoya-azul avatar Feb 19 '15 01:02 montoya-azul

@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).

GetContented avatar Jun 14 '15 05:06 GetContented

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

sophiebits avatar Jun 15 '15 02:06 sophiebits

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.

syranide avatar Jun 15 '15 08:06 syranide