Home > database >  Typing a letter in the middle of a string takes the cursor back to the end - Material UI
Typing a letter in the middle of a string takes the cursor back to the end - Material UI

Time:04-19

I implemented a ChipInput component which when focused will behave a string and onBlur will be transformed into a Chip component with the chips introduced by a comma. All works well except for a single issue. When I type in multiple words, and I want to add a new letter in between, the cursor takes me to the end but I want the cursor to stay at the same position.

Could someone please help me out? Thanks.

enter image description here

This is my Stackblitz link

CodePudding user response:

This issue occurs because the ChipInput component is rerendered every time there is a change in the value of name in index.tsx.

One solution to this problem is to change the way state inside ChipInput.tsx is updated.

  1. Firstly, remove the following useEffect code from ChipInput.tsx:
  useEffect(() => {
    setState({
      inputValue: values,
      value: compact(map(split(values, separator), (i) => trim(i))),
    });
  }, [values]);
  1. Change the initial value of state to:
  const [state, setState] = useSetState<IChipInputState>({
    value: compact(map(split(values, separator), (i) => trim(i))),
    inputValue: values,
    isFocused: false,
  });
  1. Modify the setState statement the deleteChip function to:
    setState({
      value: newChipValues,
      inputValue: join(newChipValues, `${separator} `),
      isFocused: false,
    });

The deleteChip function would then look like:

  const deleteChip = (chipValue: string): void => {
    const newChipValues = without(state.value, chipValue);
    setState({
      value: newChipValues,
      inputValue: join(newChipValues, `${separator} `),
      isFocused: false,
    });
    onHandleChange(join(newChipValues, `${separator} `), name);
  };
  1. Finally add
setState(prev => ({...prev, inputValue: onChangeValue }));

to the end of the onInputChange prop of the Autocomplete component in ChipInput.tsx. The onInputChange prop would then look like:

      onInputChange={(event, newInputValue) => {
        let onChangeValue = newInputValue;
        if (acceptOnlyNumbers) {
          onChangeValue = replace(newInputValue, /[^\d, ]/, '');
        }
        if (acceptOnlyNumbersPercentage) {
          onChangeValue = replace(newInputValue, /[^\d,% ]/, '');
        }
        onHandleChange(onChangeValue, name);
        setState(prev => ({...prev, inputValue: onChangeValue }));
      }}
  • Related