Programming Player
Programming Player

Reputation: 15

How to type unique letters only in input text box in html or react?

I want to create an input box that allows to type only a distinct alphabet letter in the input box ( No duplicate alphabet value, ONLY ONE)

I looked up all the attributes for input box but I couldn't find one and there were no example.

Do I have to handle it within JavaScript functions? (I am using React)

<input
            className="App-Contain-Input"
            name="containedLetter"
            type={"text"}
            onChange={containedChange}
          />

Upvotes: 1

Views: 1582

Answers (6)

John Detlefs
John Detlefs

Reputation: 1037

A way to do it with a cheeky two-liner is to get rid of any non-letters with regex, then let Set do the de-duping by converting to Array => Set => Array => String:

As a side note, many of the other solutions posted here make one or both of two assumptions:

  1. The user is only ever going to edit the last character... but what if they edit from the beginning or middle? Any last character solution will then fail.
  2. The user will never copy/paste a complete value... again, if they do, most of these solutions will fail.

In general, it's best to be completely agnostic as to how the value is going to arrive to the input, and simply deal with the value after it has arrived.

import { useState } from 'react';

export default function Home() {
    const [value, setValue] = useState('');

    return (
        <div>
            <input
                type='text'
                value={value}
                onChange={(e) => {
                    const onlyLetters = e.target.value.replace(/[^a-zA-Z]/g, '');
                    setValue(Array.from(new Set(onlyLetters.split(''))).join(''));
                }}
            />
        </div>
    );
}

Upvotes: 0

Raj
Raj

Reputation: 421

One pure js solution would be to handle the input value in onkeyup event where we have access to the latest key as well as updated input target value.

If the latest key pressed is duplicate then we will found it on 2 location in the target value, first on some where middle of the target value and second at the end of the target value. So we can remove the value at the end (which is the duplicate one).

The below code snippet shows the implementation of above in React

const Input = () => {
  const handleKeyUp = (e) => {
    const { key, target: { value }} = e;
    const len = value.length;

    if (value.indexOf(key) < len - 2) {
        e.target.value = value.slice(0, len - 1);
    }
  }

  return (
    <div>
      <label>Unique Keywords</label>
      <input type="text" placeholder="my-input" onKeyUp={handleKeyUp} />
    </div>
  );
}

Upvotes: 0

Andy
Andy

Reputation: 63550

Use a state to maintain the current value of the input. Then when the value changes get the last letter of the input, check that it's a letter, and if it is a letter and it isn't already in the state, update the state with the new input value.

const { useState } = React;

function Example() {

  const [ input, setInput ] = useState('');

  function handleChange(e) {
    const { value } = e.target;
    const lastChar = value.slice(-1);
    const isLetter = /[a-zA-Z]/.test(lastChar);
    if (isLetter && !input.includes(lastChar)) {
      setInput(value);
    }
  }

  function handleKeyDown(e) {
    if (e.code === 'Backspace') {
      setInput(input.slice(0, input.length - 1));
    }
  }

  return (
    <input
      value={input}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
    />
  );

}

ReactDOM.render(
  <Example />,
  document.getElementById('react')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

Upvotes: 0

A G
A G

Reputation: 22597

An isogram is a word with no repeating letters. You can check this using regex

function isIsogram (str) {
    return !/(.).*\1/.test(str);
}

Or using array.some

function isIsogram(str) {
    var strArray = str.split("");
     return !strArray.some(function(el,idx,arr){
       return arr.lastIndexOf(el)!=idx;
     });
}

In react - you need to use state to reject inputs which contain repeated letters (not an Isogram). Complete example on codesandbox.

import { useState } from 'react';

export default function App() {
  const [ text, setText ] = useState('');

  function isIsogram(str) {
    var strArray = str.split("");
     return !strArray.some(function(el,idx,arr){
       return arr.lastIndexOf(el)!==idx;
     });
}

  function handleChange(e) {
    const { value } = e.target;
    console.log(isIsogram(value));
    if (value.length === 1 || isIsogram(value)) {
      setText(value);
    }
  }

  return (
    <input value={text} onChange={handleChange} />
  );
}

Upvotes: 0

genuinestalwart
genuinestalwart

Reputation: 1

Your containedChange function can be like this:

const containedChange = (e) => {
    const value = e.target.value;
    const lastChar = value[value.length - 1];

    if (value.slice(value.length - 1, value.length).indexOf(lastChar) != -1) {
        // show error message
    }

The function checks whether the last entered character already exists in the previous value or not.

Upvotes: 0

Silviu-Marian
Silviu-Marian

Reputation: 10927

Here is how this can be done, note that we have to use onkeydown which fires when a key is being pressed, but not before it is being released (this way we can intercept and prevent the key stroke from being taken into account):

function MyInput() {

  const containedChange = (event) => {
    if (event.key.length === 1 && event.code.startsWith('Key') && event.code.length === 4 && event.target.value.indexOf(event.key) !== -1) {
      event.preventDefault()
      return false;
    }
    
    return true
  }
          
          
  return (
    <input
      id="input"
      className="App-Contain-Input"
      name="containedLetter"
      type="text"
      onkeydown={containedChange}
    />
}

Upvotes: 2

Related Questions