[Vue] vee-validate 유효성 검사 (feat. Vuetify)

suhanLee·2022년 7월 8일
0

vue-basic

목록 보기
25/29
$ npm i vee-validate@3 --save

필수, 영문, 숫자, 최대 10글자

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 영문, 숫자, 최대 10글자
			<ValidationProvider
				v-slot="{ errors }"
				name="아이디"
				:rules="{
					required: true,
					max: 10,
					alpha_num: true,
				}">
				<v-text-field
					v-model="value"
					:error-messages="errors"
					label="로그인 아이디"
					required
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value='';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 공백 불가

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 공백불가
			<ValidationProvider
				v-slot="{ errors }"
				name="이름"
				:rules="{ required: true, not_space: true }">
				<v-text-field
					v-model="value"
					:error-messages="errors"
					label="아이디 찾기 - 이름"
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 이메일 형식

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 이메일 형식
			<ValidationProvider
				v-slot="{ errors }"
				name="이메일"
				:rules="{ required: true, email: true }">
				<v-text-field
					v-model="value"
					:error-messages="errors"
					label="아이디 찾기 - 이메일"
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 숫자 자리수 제한

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 숫자 자리수 제한
			<ValidationProvider
				v-slot="{ errors }"
				name="인증번호"
				:rules="{ required: true, digits: 6 }">
				<v-text-field
					v-model="value"
					:error-messages="errors"
					label="아이디 전체 보기 - 인증번호"
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 숫자만, 전화번호정규식(커스텀valid)

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 숫자만, 전화번호정규식(커스텀valid)
			<ValidationProvider
				v-slot="{ errors }"
				name="휴대폰번호"
				:rules="{ required: true, numeric: true, phone_valid: true }">
				<v-text-field
					v-model="value"
					:error-messages="errors"
					label="회원가입 - 휴대폰번호"
					required
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 바이트 체크 (커스텀valid)

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 바이트체크 (커스텀valid)
			<ValidationProvider
				v-slot="{ errors }"
				name="프로모션명(바이트)"
				:rules="{
					required: true,
					check_byte: byte_valid && limit_byte,
				}">
				<v-text-field
					v-model="value"
					:error-messages="errors"
					label="주문/결제 - 프로모션명(바이트)"
					@keyup="byteLengthOracle(10, $event)"
					counter
					:counter-value="() => `${text_byte} / ${limit_byte}`"
					required
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
			byte_valid: false,
			text_byte: 0,
			limit_byte: 0,
		}),
		methods: {
			byteLengthOracle(limit_byte, event) {
				let value = event.target.value;
				let byte = 0;
				for (let i = 0; i < value.length; i++) {
					if (value.charCodeAt(i) > 127) {
						byte += 3;
					} else {
						byte++;
					}
				}
				//return byte;
				this.byte_valid = false;
				this.text_byte = byte;
				this.limit_byte = limit_byte;
				if (byte > limit_byte) {
					this.byte_valid = true;
				}
			},
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>


필수, 번호검사 버튼 클릭 체크 (커스텀valid)

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 번호검사 버튼 클릭 체크 (커스텀valid)
			<ValidationProvider
				v-slot="{ errors }"
				name="수신자번호 검사"
				:rules="{ required: true, phone_check: check_phone_btn }">
				<v-textarea
					label="수신자번호 검사"
					no-resize
					rows="3"
					:error-messages="errors"
					v-model="order_payment_recive_name"
					@keydown="check_phone_btn = true"
				/>
			</ValidationProvider>
			<v-btn @click="check_phone_btn = false">검사!</v-btn>
			<br />
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
			check_phone_btn: false,
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 체크박스 (커스텀valid)

타입별로 required 가능 한지 확인필요

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, (체크박스 선택)
			<ValidationProvider
				v-slot="{ errors }"
				:rules="{ required_check: true }"
				name="약광동의">
				<v-checkbox
					v-model="value"
					:error-messages="errors"
					value="1"
					label="약관동의 체크"
					type="checkbox"
					required
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 셀렉트박스 (커스텀valid)

타입별로 required 가능 한지 확인필요

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수(셀렉트박스 예제)
			<ValidationProvider
				v-slot="{ errors }"
				name="셀렉트~~"
				:rules="{ required_select: true }">
				<v-select
					v-model="value"
					:items="items"
					:error-messages="errors"
					label="셀렉트박스"
					data-vv-name="select"
					required
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			value: '',
			items: ['Item 1', 'Item 2', 'Item 3', 'Item 4'],
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.value = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

필수, 비밀번호(특수,영문,숫자조합 10자리이상 20자리 이하 - 커스텀valid)

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			필수, 비밀번호(특수,영문,숫자조합 10자리이상 20자리 이하 - 커스텀valid)
			<ValidationProvider
				v-slot="{ errors }"
				name="비밀번호재설정_비번"
				:rules="{ required: true, password_valid: true }">
				<v-text-field
					v-model="pass1"
					:error-messages="errors"
					label="비밀번호 재설정 - 비밀번호"
				/>
			</ValidationProvider>
			필수, 비밀번호 일치
			<ValidationProvider
				v-slot="{ errors }"
				name="비밀번호 확인"
				vid="confirm"
				:rules="{
					required: true,
					confirmed: '비밀번호재설정_비번',
				}"

				<v-text-field
					v-model="pass2"
					:error-messages="errors"
					label="비밀번호 재설정 - 비밀번호 확인"
				/>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		data: () => ({
			pass1: '',
			pass2: '',
		}),
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.pass1 = '';
				this.pass2 = '';
				this.$refs.observer.reset();
			},
		},
	};
</script>

파일 형식(jpg, xls...), 용량(KB..) 사이즈(너비, 높이), mime 체크

<template>
	<ValidationObserver ref="observer" v-slot="{ invalid }">
		<form @submit.prevent="submit">
			파일 형식(jpg, xls...), 용량(KB..) 사이즈(너비, 높이) 체크
			<ValidationProvider
				ref="provider"
				name="이거"
				:rules="{
					required: true,
					ext: ['txt', 'jpg', 'jpeg', 'png'],
					mimes: ['image/jpeg'],
					size: 1, // 1KB
					dimensions: '500,500', //500pixel
				}"
				v-slot="{ errors }">
				image<!-- accept="image/*" -->
				xls<!-- accept="application/vnd.ms-excel" -->
				xlsx<!-- accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" -->
				pdf<!-- accept="application/pdf" -->
				<!-- mimes: [
						'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
				], -->
				<p>
					<input ref="file1" type="file" @change="selected" />
				</p>
				<span>{{ errors }}</span>
			</ValidationProvider>
			<v-btn class="mr-4" type="submit" :disabled="invalid"> submit </v-btn>
			<v-btn @click="clear"> clear </v-btn>
		</form>
	</ValidationObserver>
</template>
<script>
	import Valid from '@/utils/Valid.vue';
	export default {
		mixins: [Valid],
		methods: {
			submit() {
				this.$refs.observer.validate();
			},
			clear() {
				this.$refs.file1.value = ''; //파일도 초기화
				this.$refs.observer.reset();
			},
			async selected({ target: { files } }) {
				const valid = await this.$refs.provider.validate(files[0]);
				if (!valid.valid) {
					console.log('not valid');
					return;
				}
				console.log('valid');
			},
		},
	};
</script>

파일 형식
참고 출처 : https://opensrc.tistory.com/142

공통 믹스인 셋팅파일

src/mixins/ValidMixin.vue

<script>
	import {
		alpha_num,
		required,
		digits,
		email,
		confirmed,
		max,
		regex,
		numeric,
		dimensions,
		ext,
		size,
		mimes,
	} from 'vee-validate/dist/rules';
	import { extend, ValidationObserver, ValidationProvider } from 'vee-validate';

	//	setInteractionMode('eager');

	//message: '{_field_} zzz needs to be {length} digits. ({_value_})',

	// 영문, 숫자체크
	extend('alpha_num', {
		...alpha_num,
		message: '영문과 숫자만 입력해주세요.',
	});

	// 숫자 체크
	extend('numeric', {
		...numeric,
		message: '숫자만 입력해주세요.',
	});
	// 숫자 체크+ 자릿 수
	extend('digits', {
		...digits,
		message: '숫자 {length}자리를 입력해주세요.',
	});

	// 필수 체크
	extend('required', {
		...required,
		message: '{_field_}를 입력해주세요.',
	});

	// 필수 체크 (체크박스)
	extend('required_check', {
		...required,
		message: '{_field_}를 체크해주세요.',
	});

	// 필수 체크 (셀렉트박스)
	extend('required_select', {
		...required,
		message: '{_field_}를 선택해주세요.',
	});

	//최대 자릿수
	extend('max', {
		...max,
		message: '{_field_}는 {length}자 이하로 입력해주세요.',
	});

	// 정규식
	extend('regex', {
		...regex,
		message: '{_field_}의 {_value_}값이 형식에 맞지 않습니다.',
		//message: '{_field_}의 {_value_} does not match {regex}',
	});

	//이메일
	extend('email', {
		...email,
		message: '이메일 형식이 올바르지 않습니다.',
	});

	extend('confirmed', {
		...confirmed,
		message: '비밀번호가 일치하지 않습니다.',
	});

	extend('dimensions', {
		...dimensions,
		message: '이미지 사이즈를 확인해주세요.',
	});

	extend('ext', {
		...ext,
		message: '파일 형식이 올바르지 않습니다.',
	});

	extend('size', {
		...size,
		message: '파일크기를 초과!',
	});
	extend('mimes', {
		...mimes,
		message: '파일 mimes포맷 불일치',
	});

	/**
	 * 커스텀 영역
	 */

	//공백 불가
	extend('not_space', {
		validate: value => {
			let regex = value.search(/\s/);
			if (regex !== -1) {
				return '공백을 제거해주세요.';
			} else {
				return true;
			}
		},
	});

	//비밀번호 특수 + 영문 + 숫자
	extend('password_valid', {
		validate: value => {
			/* eslint-disable */
			const regExp = /^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{10,20}$/;
			if (!regExp.test(value)) {
				return '영문, 숫자, 특수문자를 조합한 10자리 이상 20자리 이하 비밀번호를 입력해 주세요. ';
			} else {
				return true;
			}
		},
	});

	//휴대폰번호 정규체크
	extend('phone_valid', {
		validate: value => {
			/* eslint-disable */
			const regExp = /^(?:(010\d{4})|(070\d{4})|(01[1|6|7|8|9]\d{3,4}))(\d{4})$/;
			
			if (!regExp.test(value)) {
				return '휴대번호를 정확히 입력해주세요.';
			} else {
				return true;
			}
		},
	});
	
	//수신자번호 번호 검사 확인
	extend('phone_check', {
		validate: value => {
			return '휴대번호 검사를 실행해주세요.';
		},
	});

	//바이트 체크
	extend('check_byte', {
		validate: (value,values) => {
			const limit_byte = values[0];
			return `${limit_byte}byte를 초과할 수 없습니다.`;
		},
	});
/****************************************************
 * 바이트 체크 오라클 한글 3바이트처리
 ****************************************************/
// function byteLengthOracle1(value) {
// 	let byte = 0;

// 	for (let i = 0; i < value.length; i++) {
// 		if(value.charCodeAt(i) > 127){
// 			byte += 3;
// 		}else{
// 			byte++;
// 		}
// 	}
// 	return byte;
//}
/****************************************************
 * 바이트 체크 기본
 ****************************************************/
// function byteLength(value) {
// 	let byte = 0;

// 	for (let i = 0; i < value.length; i++) {
// 		var ch = value.charAt(i);

// 		if (escape(ch).length > 4) {
// 			// 한글일경우
// 			byte += 2;
// 		} else if (ch == '\n' || ch == '\r') {
// 			byte += 1;
// 		} else if (ch == '<' || ch == '>') {
// 			// 특수문자는 4byte
// 			byte += 4;
// 		} else {
// 			//나머지는 모두 1byte
// 			byte += 1;
// 		}
// 	} //END FOR
// 	return byte;
// }
	export default {
		components: {
			ValidationProvider,
			ValidationObserver,
		},
	};
</script>

0개의 댓글