grabury
grabury

Reputation: 5599

Is it possible to show a caps lock indicator on a password field in formik?

I want to show a capslock indicator on a password field in a formik form. I need to detect onKeyUp events, is this (detecting keyboard events) possible using formik and the password field component?

Upvotes: 4

Views: 4006

Answers (2)

R. Gillie
R. Gillie

Reputation: 1443

Old, but here's a hook for it using TypeScript:

import { useEffect, useState } from 'react';

type KeyLock = 'CapsLock' | 'NumLock' | 'ScrollLock';
const useKeyLock = (key: KeyLock) => {
  const [toggled, setToggled] = useState(false);

  useEffect(() => {
    const onKeyDown = (event: KeyboardEvent) => setToggled((pToggled) => event.getModifierState?.(key) ?? pToggled);

    document.addEventListener('keydown', onKeyDown);
    return () => document.removeEventListener('keydown', onKeyDown);
  }, [key]);

  return toggled;
};
export default useKeyLock;

and it could be used like

const YourForm = () => {
  const capsLock = useKeyLock('CapsLock');

  return (
    <form>
      <label>Password</label>
      <input type="password" />
      {capsLock && <div>Caps Lock Enabled</div>}
    </form>
  )
}

Upvotes: 5

Ciar&#225;n Tobin
Ciar&#225;n Tobin

Reputation: 7536

This doesn't really have anything to do with Formik particularly. You can just use onKeyDown() like you would on a normal input:

class Login extends React.PureComponent {
  state = { warning: false };

  /**
   * Hide warning when losing focus.
   * @param handleBlur Formik blur event.
   * @param event      Input event.
   */
  onBlur(handleBlur, event) {
    this.setState({ warning: false });
    handleBlur(event);
  }

  /**
   * Detect caps lock being on when typing.
   * @param keyEvent On key down event.
   */
  onKeyDown = keyEvent => {
    if (keyEvent.getModifierState("CapsLock")) {
      this.setState({ warning: true });
    } else {
      this.setState({ warning: false });
    }
  };

  /**
   * Show a password field that detects the caps lock key.
   * @returns Form with a password field.
   */
  render() {
    return (
      <Formik initialValues={{ password: "" }}>
        <Form>
          <label htmlFor="password">Password</label>
          <Field name="password">
            {({ field }) => (
              <input
                {...field}
                id="password"
                onBlur={this.onBlur.bind(this, field.handleBlur)}
                onKeyDown={this.onKeyDown}
                type="password"
              />
            )}
          </Field>
          {this.state.warning && <div>Caps Lock On!</div>}
        </Form>
      </Formik>
    );
  }
}

See it working here.

This is a minimal example. I would probably throttle the onKeyDown() check.

Upvotes: 5

Related Questions