vee-validate로 input의 내용들을 검사 해 보자

안상철·2023년 1월 8일
0

Vue.js

목록 보기
8/9
post-thumbnail

vee-validate는 많이 알려진 input 유효성 검사 라이브러리이다.

vue2와 vue3에서 사용하는 차이점이 있는데

  • vue2에서는 직접 componentId를 할당해 validation이 필요한 곳에 삽입 해 주면 되고
  • vue3에서는 Form태그 안에 감싸면 validation이 이루어지더라

vue2

import Vue from 'vue'
import { ValidationProvider, extend, ValidationObserver, localize } from 'vee-validate'
import * as rules from 'vee-validate/dist/rules'
import ko from 'vee-validate/dist/locale/ko.json'
import en from 'vee-validate/dist/locale/en.json'

import {
i18n
} from '@/plugins/i18n'
const customValidate = require.context('@/assets/lang/veeValidate', true, /[A-Za-z0-9-_,\s]+.json$/i)

// loop over all rules
for (let rule in rules) {
extend(rule, rules[rule])
}

const customLocalize = {}
customValidate.keys().forEach(key => {
const matched = key.match(/([A-Za-z0-9-_]+)./i)
if (matched && matched.length > 1) {
const locale = matched[1]
let tmpMessages = customLocalize[locale] || {}
customLocalize[locale] = Object.assign(tmpMessages, customValidate(key))
}
})

localize(i18n.locale)
localize({
ko: Object.assign(ko, customLocalize.ko),
en: Object.assign(en, customLocalize.en)
})
Vue.component('ValidationProvider', ValidationProvider)
Vue.component('ValidationObserver', ValidationObserver)


회사에서는 다국어 처리 프로세스가 있기 때문에 i18n 라이브러리를 사용해 validation 메세지를 커스텀 한 것으로 보인다. i18n에 대해서는 아직 아는게 많이 없기 때문에 더 공부하고 다음 포스팅에 작성 해 보도록 하겠다..

아무튼 vee-validation 라이브러리를 다운 받은 다음 아래 Vue.componet 구문에 각 Id를 할당해 컴포넌트에서 꺼내 사용하는 형식이다.

로그인 컴포넌트를 확인 해 보자
    <ValidationObserver v-slot="{ passes }">
      <form @submit.prevent="passes(_login)">
        <div class="input-group without-label">
          <input-text
            v-model="userId"
            name="userId"
            :label="$t('attributes.userId')"
            rules="required"
            input-type="text"
            error-msg-class="errors-msg"
            :placeholder="$t('user.id_placeholder')"
          ></input-text>
        </div>
        <div class="input-group without-label">
          <input-text
            v-model="password"
            name="password"
            :label="$t('attributes.password')"
            :rules="{ required: true, max: 16, regex: /(?=.*\d{1,})(?=.*[~`!@#$%\^&*()-+=]{1,})(?=.*[a-z]{1,})(?=.*[A-Z]{1,}).{8,16}$/ }"
            input-type="password"
            error-msg-class="errors-msg"
            :placeholder="$t('user.pw_placeholder')"
          ></input-text>
        </div>
        <div>
          <button data-cy="login" class="btn gradient-btn">{{ $t("user.login") }}</button>
        </div>

        <div>
          <user-captcha
            :user-id="captcha.userId"
            :response.sync="captcha.response"
            :is-show="captcha.isShow"
          ></user-captcha>
        </div>

        <div class="user-login-other-actions">
          <div class="left">
            <router-link :to="{ name: 'user-agree' }">{{ $t("user.sing_up") }}</router-link>
          </div>
          <div class="right" :class="{ kor : currentLocale == 'ko' }">
            <!-- <router-link :to="{ name: 'user-find-id' }">{{ $t("user.find.id") }}</router-link> -->
            <router-link :to="{ name: 'user-find-pwd' }">{{ $t("user.find.pw") }}</router-link>
          </div>
        </div>
      </form>
    </ValidationObserver>

위아래 잡다한 코드는 생략하고 ValidationObserver가 적용 되어 있는 부분만 발췌했다.
ValidationObserver태그로 감싸진 부분은 vee-validation이 적용되어 rules="required" 속성을 넣어주면 미리 정해놓은 rule에 따라 validation이 진행된다.
error-msg-class="errors-msg"는 validation에 걸렸을 때 에러 메세지를 나타내는 클래스를 넣어준다.

input-text도 커스텀 해서 사용했는데 속성의 인자로 넘겨준 rules부분에는
<ValidationProvider
:vid=id
:name="name"
:rules="rules"
v-slot="{ errors, invalid }">
  <div v-if="label" :class="labelClass">{{ label }}<span v-if="required" class="required"></span>
  </div>
  <input />
  <span :class="errorMsgClass" v-if="invalid" >{{ errors[0] }}</span>
</ValidationProvider>

아래처럼 ValidationProvider로 감싸져있다. 에러 메세지 클래스는 v-slot으로 바인드 되었기 때문에 에러가 발생 할 경우 나타난다.

> vue3

import { defineRule, configure } from 'vee-validate'
import { localize } from '@vee-validate/i18n'
import AllRules from '@vee-validate/rules'
import en from '@vee-validate/i18n/dist/locale/en.json'
import ko from '@vee-validate/i18n/dist/locale/ko.json'
import { i18n } from '@/plugins/i18n'

Object.keys(AllRules).forEach((rule) => {
defineRule(rule, AllRules[rule])
})

const customValidate = require.context(
'@/assets/lang/veeValidate',
true,
/[A-Za-z0-9-_,\s]+.json$/i
)
const customLocalize = {}
customValidate.keys().forEach((key) => {
const matched = key.match(/([A-Za-z0-9-_]+)./i)
if (matched && matched.length > 1) {
const locale = matched[1]
const tmpMessages = customLocalize[locale] || {}
customLocalize[locale] = Object.assign(tmpMessages, customValidate(key))
}
})
localize(i18n.global.locale.value)

configure({
validateOnInput: true,
generateMessage: localize({
ko: Object.assign(ko, customLocalize.ko),
en: Object.assign(en, customLocalize.en)
})
})


vue3는 vue2와 크게 달라진 점은 없지만 id를 할당하지 않고 configure구문에 작성한다.
똑같이 login컴포넌트와 input을 살펴보자
    <Form @submit="_login">
      <input-text
        name="userId"
        :rules="{ required: true }"
        v-model="userId"
        label="아이디"
        type="textArea"
      />
      <input-text
        name="password"
        type="password"
        :rules="{
          required: true,
          max: 16,
          regex:
            /(?=.*\d{1,})(?=.*[~`!@#$%\^&*()-+=]{1,})(?=.*[a-z]{1,})(?=.*[A-Z]{1,}).{8,16}$/,
        }"
        v-model="password"
        label="비밀번호"
      />
      <button class="btn btn-primary">{{ t("login_label") }}</button>
    </Form>
{{ label }}
```

validationObserver 대신 Form태그로 감쌌고 provider 대신 Field 태그로 validation을 걸어준다. ErroMessageClass도 slot으로 구현하지 않고 직접 넣어준다.

두 버전 모두 validation에 걸리면 submit에 작성 한 메서드가 실행되지 않는다.

profile
웹 개발자(FE / BE) anna입니다.

0개의 댓글