92. Validation Components

npm create vue@latest


Validate가 준비되었습니다.
이 강의에서는 입력 필드의 유효성을 검증할 시간입니다.
이전에 등록한 컴포넌트들을 사용하기 시작할 것입니다.
이전 섹션에서 준비한 모델을 사용하고 있습니다.
로그인과 등록 양식이라는 두 가지 양식이 있습니다.
우리는 등록 양식의 유효성을 검증하기 시작할 것입니다.
이 양식에는 일반적으로 등록 양식에 나타나지 않는 추가 필드가 있습니다.
최소한 이메일, 사용자 이름 및 비밀번호를 요청하는 것이 일반적입니다.
시연 목적으로 추가 필드를 추가하기로 결정했습니다.
이를 통해 다양한 유형의 입력 필드를 어떻게 검증하는지 살펴볼 기회를 갖게 될 것입니다.
이제 개요를 알았으니, 편집기로 전환하여 인증 컴포넌트 내의 등록 양식을 찾아봅시다.
양식에 대한 주석이 있는데, 그것은 등록 양식을 나타냅니다.
원한다면, 등록 양식에 더 집중하기 위해 로그인 양식을 접을 수 있습니다.
우리는 한동안 로그인 양식을 다루지 않을 것입니다.
양식의 첫 번째 필드는 이름을 위한 텍스트 필드이며, 독특한 속성은 없습니다.
이 강의의 목표는 이 필드의 유효성을 검증하는 것입니다.
우리는 한 가지 규칙을 사용할 것입니다.

이름을 필수 필드로 만들고 싶습니다.
이미 HTML5에 'required'라는 속성이 있는데, 이것은 필드가 비어 있을 때 양식의 제출을 방지합니다.
그것은 옵션이지만, 우리는 그것을 사용하지 않을 것입니다.
대신 validate를 사용하면 오류에 대해 더 나은 제어를 할 수 있기 때문입니다.

첫 번째 단계는 등록 양식의 form 요소를 VeeForm 컴포넌트로 교체하는 것입니다.
VeeForm 컴포넌트의 역할은 양식 내에서 일련의 유효성 검사를 조직하는 것이며, 이 컴포넌트를 통해 양식을 전역적으로 제어할 수 있습니다.
양식의 모든 입력 필드가 유효한지 확인하는 데 도움이 됩니다.
VeeForm 컴포넌트는 기본적으로 컴포넌트를 감싸는 태그를 생성합니다.
기본적으로 form 태그를 사용합니다.
이것이 왜 우리가 form 요소를 VeeForm 컴포넌트로 안전하게 교체할 수 있는지를 설명합니다.
구체적으로 검증하고 싶은 것은 입력 필드에서의 값입니다.

기본적으로, VALIDATE는 내부에 배치된 요소에 대해 자동으로 유효성 검사를 수행하지 않습니다.
명시적으로 어떤 입력이 유효성 검사되어야 하는지 알려주어야 합니다.
이전 강의에서 등록한 VeeField 컴포넌트를 사용하여 알릴 수 있습니다.
이름을 위한 입력부터 시작할 것입니다.
이것은 양식의 첫 번째 입력입니다.
우리는 입력 요소를 VeeField 컴포넌트로 변경할 것입니다.
VeeField 컴포넌트는 단일 입력의 유효성을 검증하는 책임이 있으며, 기본적으로 input 태그를 생성합니다.
입력 요소를 이 컴포넌트로 안전하게 교체할 수 있습니다.
생성되는 요소를 오버라이드하고 싶다면, as라는 속성을 추가할 수 있습니다.
이 속성의 값은 컴포넌트가 생성하고자 하는 태그의 이름입니다.

예를 들어, select 요소를 생성하고 싶다면 select를 전달할 수 있습니다.
원래 태그는 input 태그였기 때문에, 우리는 이 속성을 제거할 것입니다.
우리에게 필요하지 않기 때문입니다.
이 강의의 리소스 섹션에서는 field 컴포넌트 문서 페이지에 대한 링크를 제공합니다.
아래로 스크롤하면 Properties라는 섹션을 볼 수 있는데, 여기에는 컴포넌트의 동작을 수정할 수 있는 속성 목록이 있습니다.
이 목록에서 as 속성을 찾을 수 있으며, 이 속성은 컴포넌트가 출력할 태그의 이름입니다.
기본 태그는 input이며, 우리가 사용하는 라이브러리의 문서를 확인하여 어떤 것이 렌더링될지 확인하는 것이 항상 좋은 아이디어입니다.

편집기로 돌아가 보겠습니다.
문서화되어 있지 않지만, 컴포넌트에 추가하는 모든 속성은 컴포넌트가 출력하는 요소에 자동으로 추가됩니다.
이것이 컴포넌트의 공식 속성이 아닌 한, 그것은 요소에 수동적으로 추가됩니다.
입력에 class 속성을 다시 적용할 필요가 없습니다.

다음으로 할 일은 validate에 입력을 어떻게 검증해야 할지 알려주는 것입니다.
입력을 검증하기 위한 네 단계가 있습니다.
첫 번째 단계는 입력을 VeeField 컴포넌트로 교체하는 것입니다.
우리는 이미 그것을 했습니다.

두 번째 단계는 우리가 검증할 입력에 이름을 할당하는 것입니다.
우리는 여러 입력을 검증할 것이므로, validate는 각 입력을 식별할 수 있는 방법이 필요합니다.
이것은 잠시 후에 살펴볼 것입니다.

세 번째 단계는 규칙을 추가하는 것입니다.
규칙은 값이 유효하다고 간주되기 위해 충족해야 할 일련의 기준을 말합니다.
마지막으로, 사용자의 입력이 어떤 규칙에도 부합하지 않는 경우 오류를 처리하는 방법이 필요합니다.
사용자에게 그들의 오류를 어떻게 수정할 수 있는지 피드백을 주는 것이 중요합니다.

편집기로 돌아가서 입력에 고유 식별자를 할당하는 방법을 처리할 것입니다.
이것은 validate가 우리의 양식을 더 잘 이해하는 데 도움이 될 것입니다.
VeeField 컴포넌트에 name 속성을 추가하여 식별자를 추가할 수 있습니다.
이름을 name으로 설정할 것입니다.

다음 단계로 규칙을 추가하는 것으로 넘어갈 것입니다.

src/components/AppAuth.vue
<script setup lang="ts">
import useModal from '@/stores/modal'
import { storeToRefs } from 'pinia'
import { ref } from 'vue'

const modalStore = useModal()
const { hiddenClass, isOpen: modalVisibility } = storeToRefs(modalStore)

const tab = ref('login')
</script>

<template>
  <!-- Auth Modal -->
  <div class="fixed z-10 inset-0 overflow-y-auto" id="modal" :class="hiddenClass">
    <div
      class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
    >
      <div class="fixed inset-0 transition-opacity">
        <div class="absolute inset-0 bg-gray-800 opacity-75"></div>
      </div>

      <!-- This element is to trick the browser into centering the modal contents. -->
      <span class="hidden sm:inline-block sm:align-middle sm:h-screen">&#8203;</span>

      <div
        class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
      >
        <!-- Add margin if you want to see some of the overlay behind the modal-->
        <div class="py-4 text-left px-6">
          <!--Title-->
          <div class="flex justify-between items-center pb-4">
            <p class="text-2xl font-bold">Your Account</p>
            <!-- Modal Close Button -->
            <div class="modal-close cursor-pointer z-50" @click="modalVisibility = false">
              <i class="fas fa-times"></i>
            </div>
          </div>

          <!-- Tabs -->
          <ul class="flex flex-wrap mb-4">
            <li class="flex-auto text-center">
              <a
                class="block rounded py-3 px-4 transition"
                :class="{
                  'hover:text-white text-white bg-blue-600': tab === 'login',
                  'hover:text-blue-600': tab === 'register'
                }"
                href="#"
                @click.prevent="tab = 'login'"
              >
                Login
              </a>
            </li>
            <li class="flex-auto text-center">
              <a
                class="block rounded py-3 px-4 transition"
                :class="{
                  'hover:text-white text-white bg-blue-600': tab === 'register',
                  'hover:text-blue-600': tab === 'login'
                }"
                href="#"
                @click.prevent="tab = 'register'"
              >
                Register
              </a>
            </li>
          </ul>

          <!-- Login Form -->
          <form v-show="tab === 'login'">
            <!-- Email -->
            <div class="mb-3">
              <label class="inline-block mb-2">Email</label>
              <input
                type="email"
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
                placeholder="Enter Email"
              />
            </div>
            <!-- Password -->
            <div class="mb-3">
              <label class="inline-block mb-2">Password</label>
              <input
                type="password"
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
                placeholder="Password"
              />
            </div>
            <button
              type="submit"
              class="block w-full bg-purple-600 text-white py-1.5 px-3 rounded transition hover:bg-purple-700"
            >
              Submit
            </button>
          </form>
          <!-- Registration Form -->
          <VeeForm v-show="tab === 'register'">
            <!-- Name -->
            <div class="mb-3">
              <label class="inline-block mb-2">Name</label>
              <VeeField
                type="text"
                name="name"
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
                placeholder="Enter Name"
              />
            </div>
            <!-- Email -->
            <div class="mb-3">
              <label class="inline-block mb-2">Email</label>
              <input
                type="email"
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
                placeholder="Enter Email"
              />
            </div>
            <!-- Age -->
            <div class="mb-3">
              <label class="inline-block mb-2">Age</label>
              <input
                type="number"
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
              />
            </div>
            <!-- Password -->
            <div class="mb-3">
              <label class="inline-block mb-2">Password</label>
              <input
                type="password"
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
                placeholder="Password"
              />
            </div>
            <!-- Confirm Password -->
            <div class="mb-3">
              <label class="inline-block mb-2">Confirm Password</label>
              <input
                type="password"
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
                placeholder="Confirm Password"
              />
            </div>
            <!-- Country -->
            <div class="mb-3">
              <label class="inline-block mb-2">Country</label>
              <select
                class="block w-full py-1.5 px-3 text-gray-800 border border-gray-300 transition duration-500 focus:outline-none focus:border-black rounded"
              >
                <option value="USA">USA</option>
                <option value="Mexico">Mexico</option>
                <option value="Germany">Germany</option>
              </select>
            </div>
            <!-- TOS -->
            <div class="mb-3 pl-6">
              <input type="checkbox" class="w-4 h-4 float-left -ml-6 mt-1 rounded" />
              <label class="inline-block">Accept terms of service</label>
            </div>
            <button
              type="submit"
              class="block w-full bg-purple-600 text-white py-1.5 px-3 rounded transition hover:bg-purple-700"
            >
              Submit
            </button>
          </VeeForm>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped></style>