Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse moves cursor to end of input field #317

Open
joewestcott opened this issue Aug 17, 2018 · 8 comments
Open

Parse moves cursor to end of input field #317

joewestcott opened this issue Aug 17, 2018 · 8 comments

Comments

@joewestcott
Copy link

joewestcott commented Aug 17, 2018

See this example, in the username field:
https://codesandbox.io/s/10rzowm323

Typing an uppercase character moves the cursor to the end of the line. This is only visible when the cursor has characters to it's right.

@joewestcott
Copy link
Author

Related to #255?
🤔

@renato
Copy link

renato commented Aug 20, 2018

It also happens with the phone field in the same example.

@joeljeske
Copy link

I think its the typical react input cursor jump issue: facebook/react#955

@emartini
Copy link

emartini commented Dec 4, 2018

any workaround on this issue?
I'm can't figure out how to fix the issue in this example:
https://codesandbox.io/s/no20p7z3l

@emartini
Copy link

emartini commented Dec 5, 2018

Not using format and using react-text-mask worked for me:

Example:
https://codesandbox.io/s/m4183xjk5j

@taschetto
Copy link

@emartini could you solve it without react-text-mask?

@afrievalt
Copy link

New to the code base but working on a solution, attempting to add a 3rd parameter to parse callback sending old value, if new value is shorter than the old value don't parse.

// todo: add oldValue to callback
const normalizePhone = (value, field, oldValue) => {
  if (!value) return value;
  const isDelete = oldValue.length > value.length
  if(isDelete) return value;
  const onlyNums = value.replace(/[^\d]/g, "");
  if (onlyNums.length <= 3) return onlyNums;
  if (onlyNums.length <= 7)
    return `(${onlyNums.slice(0, 3)}) ${onlyNums.slice(3, 7)}`;
  return `(${onlyNums.slice(0, 3)}) ${onlyNums.slice(3, 6)}-${onlyNums.slice(
    6,
    10
  )}`;
`};`

@reinrl
Copy link

reinrl commented Oct 20, 2020

@emartini could you solve it without react-text-mask?

@taschetto I am starting to believe that what solved this for Esteban was not necessarily the use of react-text-mask - and was more importantly the result of doing his own input masking (by way of rendering a <MaskedInput> component) within the render() prop of <Field ... />, instead of using the built-in parse attribute (which I am hypothesizing suffers the ill effects of some state mutation/rerender cycles within the bowels of react-final-form, as opposed to the outside handling of the masking/transformation of the user's input that react-text-mask in Esteban's example - admittedly, I haven't taken the time yet to tweak his refenced code sandbox sufficiently to further confirm).

@erikras - Does this seem like a plausible theory/something worth investigating further?

UPDATE:
So I added a field to a fork of the codesandbox, and it appears to prove that this approach (using the Field's render prop, and effectively treating the render function like the Component prop through use of the value and onChange from the reference to input) suffers the same cursor jump issue...to a point.

The only time that I can get the cursor to not jump is when the input length is less than the allowed length (in this example, less than 10 digits entered) AND when the cursor is in the last "chunk" of the value (in this example, when the cursor is to the right of the last hyphen if any have already been added). After some more playing, this seems to be tied to whenever the value is mutated from the previous (e.g., for the phone number, I input a character to turn "123" into "1234" - and then my masking mutates it to "123-4") - meaning that input.onChange() is suffering the same ill effects of some state mutation/rerender cycles within the bowels of react-final-form? To make this more apparent, you can even attempt to manually set the cursor position with an example like this:

onChange={(event) => {
  const caretStart = event.target.selectionStart;
  const caretEnd = event.target.selectionEnd;
  onChange(
    formatString("999-999-9999", event.currentTarget.value)
  );
  event.target.setSelectionRange(caretStart, caretEnd);
}}

I am hypothesizing that the state update/rerender happening within RFF is happening after the setSelectionRange() call, so it has no visible effect. Circling back around to the react-text-mask example above (and why it works), notice that it doesn't actually set the form field value to the masked input form (instead, it has the value of the raw input - the second field is a great example of this) - so the efficacy of the solution seems to depend a lot on your requirements (Do you just need to display the mask, or are you trying to control what gets handed off to some sort of persistence mechanism?).

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

No branches or pull requests

7 participants