html input 유효성(validity) 검사

2023. 10. 14. 20:34react

React에서 폼(Form)화면 작성시 로그인 화면에서 아이디 또는 비밀번호는 필수로 입력하게하거나, 회원가입 화면에서 비밀번호 입력시 특수문자나 소문자, 대문자 또는 숫자 등을 섞어서 입력하도록 유효성 검사를 진행할때가 있습니다. React를 사용한다면 상태(state)를 통해서도 충분히 입력값의 유효성검사를 진행할 수 있지만, HTML의 <input/>에서도 유효성 검사와 관련하여 다양한 기능을 제공하고 있으니 한번 살펴보도록 하겠습니다.

현재 유효성 검사 상태를 나타내는 ValidityState

<input/>요소는 현재 유효성 상태를 나타내는 validity(ValidityState)값을 가지고 있으며, <input/>요소의 여러가지 attribute 설정과 입력값에 의해 validity의 상태가 결정됩니다.

// App.tsx
import React, { useEffect, useRef } from "react"

export default function App() {
  const _inputRef = useRef<HTMLInputElement>(null)

  useEffect(() => {
    console.log(_inputRef.current?.validity)
  }, [])

  return <input ref={_inputRef} />
}

// Console
{
  valueMissing: false,    // required
  typeMismatch: false,
  patternMismatch: false,
  tooLong: false,
  tooShort: false,
  rangeUnderflow: false,
  rangeOverflow: false,
  stepMismatch: false,
  badInput: false,
  customError: false,
  valid: true
}

validity는 각 유효성들의 검사 통과여부를 나타내는 오브젝트 형태의 값입니다. 키명칭들은 어떠한 유효성 조건인지를 나타내며 각 키의 값에는 해당 유효성 조건이 문제가 있는지 없는지를 나타내는 Boolean값이 들어있습니다. 그리고 추가적으로 전체 유효성 통과 상태를 나타내는 valid키가 포함되있습니다.
해당 키의 값은 대응하는 유효성 조건을 통과하면 false, 통과하지 못하면 true가 되며, 모든 유효성 조건을 통과하는 경우 valid키의 값은 true가 되고 하나라도 유효성 조건을 통과하지 못하면 false가 됩니다.

// 모든 유효성 검사 통과
{
  valueMissing: false,
  typeMismatch: false,
  patternMismatch: false,
  tooLong: false,
  tooShort: false,
  rangeUnderflow: false,
  rangeOverflow: false,
  stepMismatch: false,
  badInput: false,
  customError: false,
  valid: true
}

// valueMissing 유효성 검사 실패
{
  valueMissing: true,
  typeMismatch: false,
  patternMismatch: false,
  tooLong: false,
  tooShort: false,
  rangeUnderflow: false,
  rangeOverflow: false,
  stepMismatch: false,
  badInput: false,
  customError: false,
  valid: false
}

유효성 검사를 진행하는 checkValidity 또는 ReportValidity

일반적으로 유효성 검사는 해당 입력요소가 포함된 form에서 submit 이벤트가 발생되기 전에 진행되지만, checkValidityreportValidity를 사용하면 직접 유효성 검사를 진행할수 있습니다.(checkValidity와 reportValidity의 차이점이 궁금하다면 해당 포스팅을 봐주세요.)

import { FocusEvent, useState } from "react";
import "./styles.css";

export default function App() {
  const [_invalid, _setInvalid] = useState("");

  function _onBlur(event: FocusEvent<HTMLInputElement>) {
    // input에서 포커스 아웃시 유효성 검사
    const valid = event.target.checkValidity();
    if (valid) {
      _setInvalid("");
    } else {
      _setInvalid(findInvalidKey(event.target.validity));
    }
  }

  return (
    <div
      style={{
        display: "flex",
        flexDirection: "column",
        alignItems: "start",
        gap: "0.25rem"
      }}
    >
      {/* 유효성 검사 상태에 따라 스타일 변경 */}
      <input
        required
        className={_invalid === "" ? "" : "Input-invalid"}
        onBlur={_onBlur}
      />
      {_invalid && <span className={"Text-invalid"}>{_invalid}</span>}
    </div>
  );
}

function findInvalidKey(validity?: ValidityState) {
  if (validity?.badInput) {
    return "badInput";
  }
  if (validity?.customError) {
    return "customError";
  }
  if (validity?.patternMismatch) {
    return "patternMismatch";
  }
  if (validity?.rangeOverflow) {
    return "rangeOverflow";
  }
  if (validity?.rangeUnderflow) {
    return "rangeUnderflow";
  }
  if (validity?.stepMismatch) {
    return "stepMismatch";
  }
  if (validity?.tooLong) {
    return "tooLong";
  }
  if (validity?.tooShort) {
    return "tooShort";
  }
  if (validity?.typeMismatch) {
    return "typeMismatch";
  }
  if (validity?.valueMissing) {
    return "valueMissing";
  }
  return "";
}

'react' 카테고리의 다른 글

React event의 여러가지 target  (0) 2023.11.19
box-shadow로 inline border 만들기  (0) 2023.11.13
CSS BoxShadow 제대로 알기  (0) 2023.11.06
input요소 checkValidity와 reportValidity  (0) 2023.10.13
CSS Box model  (0) 2020.11.15