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

Cursor jumps to end of input #5

Open
n8sabes opened this issue Jul 5, 2022 · 19 comments · May be fixed by #170
Open

Cursor jumps to end of input #5

n8sabes opened this issue Jul 5, 2022 · 19 comments · May be fixed by #170
Assignees
Labels
enhancement New feature or request

Comments

@n8sabes
Copy link

n8sabes commented Jul 5, 2022

@viclafouch ,

Thanks for sharing your work onmui-tel-input, it's the the best React / MUI implementation I've found yet.

When editing a digit in the middle of the phone number string, upon becoming valid or invalid, the cursor jumps to the end. This makes it impossible to easily edit the area code or correct a typo.

How to reproduce:

  1. Enter +16505555555
  2. Select the area code and change it to +14155555555

The user must keep repositioning the cursor back to the edit point.

Configuration being used:

     <MuiTelInput
          onlyCountries={['US', 'MX', 'CA']}
          forceCallingCode={true}
          defaultCountry={"US"}
          value={value}
          onChange={handleChange}
          error={!isValid}
      />
@viclafouch
Copy link
Owner

Correct, let me fix that.

@viclafouch
Copy link
Owner

Okay, this seems to be more difficult than I thought. Let me back to you asap!

@viclafouch viclafouch self-assigned this Jul 6, 2022
@viclafouch viclafouch added the enhancement New feature or request label Jul 6, 2022
@n8sabes
Copy link
Author

n8sabes commented Jul 6, 2022

I've spent many hours down this rabbit hole with controlled MUI-Text as an element of a larger component. I look forward to seeing what you come up with -- and thank you. I really like your control and have ditched the previous library for mum-tel-input, even with the current selection problem.

@justinkahrs
Copy link

Hey @viclafouch is there a fix or a workaround for this?

@JayWelsh
Copy link

JayWelsh commented Mar 27, 2023

It would be great if there was a fix for this @viclafouch 🙏

@jukkahuuskonen
Copy link

@viclafouch

I had the same problem when I created a simple version of phone number input that would accepts only numbers. You can get the caret-position of the input for every input-event from the input-ref. Then you need to calculate the correct new position and set it manually.

I hope this might help you with fixing this problem.

Here are the get/set caret position functions for getting the start caret position and setting it into correct position after checking the new input (allowed digits/chars). My input accepts only numbers and it doesn't check any international formats

get/set caret position

// ctrl = html-element (inputRef.current)

export const getCaretPosition = ctrl => {
  let CaretPos = 0;

  if (ctrl.selectionStart || ctrl.selectionStart === 0) {
    // Standard.
    CaretPos = ctrl.selectionStart;
  } else if (document.selection) {
    // Legacy IE
    ctrl.focus();
    const Sel = document.selection.createRange();
    Sel.moveStart('character', -ctrl.value.length);
    CaretPos = Sel.text.length;
  }

  return CaretPos;
};

export const setCaretPosition = (ctrl, pos) => {
  if (ctrl.setSelectionRange) {
    ctrl.focus();
    ctrl.setSelectionRange(pos, pos);
  } else if (ctrl.createTextRange) {
    const range = ctrl.createTextRange();
    range.collapse(true);
    range.moveEnd('character', pos);
    range.moveStart('character', pos);
    range.select();
  }
};

export const macRegex = /^[0-9A-F]$/;

Simple Phonenumber-input component: In this example, I have replaced my StyledInput in the code with a regular <input> because pasting all the styling would have messed up the post too much. Now it looks ugly as hell, but it should work fine. the caret-position handling happens in handleChange-function. You will just have to make your own calculations for inserting/deleting spacing correctly. Mine were pretty simple here, since I only accept numbers.

import { useRef, useState } from 'react';
import styled from '@emotion/styled';
import { setCaretPosition, getCaretPosition } from 'shared/functions/inputUtils';
import { Input } from 'shared/styledTheme';
import { borderColor, boxShadowColor } from 'shared/styledTheme/Components/Input';

const Container = styled('div')`
  display: grid;
  align-items: center;
  justify-items: center;
  grid-template-columns: 1rem 1fr;
  grid-auto-flow: column;
  border-radius: 4px;
  border: 1px solid #ccc;
  margin: 0px 5px;
  &:focus-within {
    border-color: ${borderColor};
    box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 0 3px ${boxShadowColor};
    outline: none;
  }
  ${props => (props.error ? `border-color: ${borderColor(props)};` : '')}
`;

const PlusDiv = styled('div')`
  font-weight: bold;
`;

const StyledInput = styled(Input)`
  justify-self: stretch;
  border: none;
  margin: 0;
`;

const PhoneNumberInput = ({ registerRef, onChange, onBlur, error, maxDigits = 15, ...rest }) => {
  const inputRef = useRef();
  const [isFocused, setIsFocused] = useState(false);

  const handleChange = e => {
    const {
      target: { value },
    } = e;
    const caretPos = getCaretPosition(inputRef.current);
    const valueNumbers = value.replace(/\D/g, '');
    const newCaretPos = caretPos - (value.length - valueNumbers.length);
    e.target.value = valueNumbers.substring(0, maxDigits);
    setCaretPosition(inputRef.current, newCaretPos);
    onChange(e);
  };

  return (
    <Container isFocused={isFocused} error={error}>
      <PlusDiv>+</PlusDiv>
//      <StyledInput
        <input 
        ref={e => {
          registerRef(e);
          inputRef.current = e;
        }}
        onFocus={() => {
          setIsFocused(true);
        }}
        onBlur={e => {
          setIsFocused(false);
          onBlur(e);
        }}
        onChange={handleChange}
        {...rest}
      />
    </Container>
  );
};

export default PhoneNumberInput;

@CHANDRU-WMH
Copy link

Any updates, problem still exists.

@sayedi-hassan
Copy link
Contributor

sayedi-hassan commented Jul 3, 2023

hey @viclafouch
Could you kindly review this fix and confirm if it is suitable for addressing the reported issue?

@JayWelsh
Copy link

Hi @viclafouch
If you get a chance please take a look at this proposed solution 😊

@viclafouch
Copy link
Owner

Hello everyone !

Looking at the solution next week, as I am in vacation rn !

Thanks for your collab !

@jukkahuuskonen
Copy link

Hello everyone !

Looking at the solution next week, as I am in vacation rn !

Thanks for your collab !

Any news on this?

@viclafouch
Copy link
Owner

Can't release because of a bug :

#81 (comment)

@Jay-Topher
Copy link

I'm also facing this, I'd really appreciate it if this fix gets released soon, cheers

@JayWelsh
Copy link

JayWelsh commented Oct 5, 2023

@viclafouch can this issue please be reopened until it is fixed? I'm a little confused now because there doesn't seem to be an open issue tracking this bug anymore? Or has it been moved somewhere else?

@viclafouch viclafouch reopened this Oct 5, 2023
@woodsbox
Copy link

woodsbox commented Aug 4, 2024

Any updates on this?

@aleksandarkoprivica
Copy link

@viclafouch any updates on this issue?

@akyllo34
Copy link

akyllo34 commented Nov 26, 2024

Hi all, Ive had a similar issue in my code base. While positioning the caret manually can help i found the best solution to be using a wrapper around the component in question that allows the value state to be set synchronously and asynchronously at the same time. https://gist.github.com/mjsarfatti/6e1261f0be5f3c9eef5da1cda7bd3ffe

@bamoha
Copy link

bamoha commented Jan 28, 2025

I realise this happens when the input has the phone number formatting, if it doesnt, it works just fine.

Can we reopen this till its fixed @viclafouch

@kev-landry
Copy link

#170
There is a PR for this bug @viclafouch

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

Successfully merging a pull request may close this issue.