はじめに
前回実装したログイン機能に、Vuetifyでバリデーションを実装します。
公式ドキュメントを参考に進めていきます。
前回:https://qiita.com/HuntingRathalos/items/b401ee865c40e94cef46
環境
- Vue:2.6.14
- Vuetify:2.6.1
目次
1.ベースとなるコード
2.バリデーション実装
2-1.各テキストフィールドに制約をつける
2-2.フォーム全体をバリデーションチェック
3.参考記事
1. ベースとなるコード
下記のコードにバリデーションをかけていきます。
EmailInput.vue
<template>
<v-text-field
v-model="setEmail"
label="メールアドレスを入力"
placeholder="your@email.com"
type="email"
outlined
dense
rounded
/>
</template>
<script>
export default {
props: {
email: {
type: String,
default: ''
}
},
computed: {
setEmail: {
get() {
return this.email
},
set(newVal) {
return this.$emit('update:email', newVal)
}
}
}
}
</script>
PasswordInput.vue
<template>
<v-text-field
v-model="setPassword"
type="password"
label="パスワードを入力"
placeholder="8文字以上"
outlined
rounded
dense
/>
</template>
<script>
export default {
props: {
password: {
type: String,
default: ''
}
},
computed: {
setPassword: {
get() {
return this.password
},
set(newVal) {
return this.$emit('update:password', newVal)
}
}
}
}
</script>
pages/login.vue
<template>
<v-card max-width="500" class="mx-auto mt-5 full-width" flat outlined>
<v-card-title class="text-center pa-8">
<h1 class="text-h5 font-weight-bold full-width">ログイン情報入力</h1>
</v-card-title>
<v-divider> </v-divider>
<div class="px-6 py-8">
<div style="max-width: 336px" class="mx-auto">
<v-card-text>
<v-form @submit.prevent="doLogin">
<email-input :email.sync="form.email" />
<password-input :password.sync="form.password" />
<v-card-actions>
<v-row justify="end" class="pb-8 pt-4">
<base-button :color="btnColor">ログイン</base-button>
</v-row>
</v-card-actions>
</v-form>
</v-card-text>
</div>
</div>
</v-card>
</template>
<script>
import BaseButton from '../../atoms/buttons/BaseButton.vue'
import EmailInput from '../../atoms/inputs/EmailInput.vue'
import PasswordInput from '../../atoms/inputs/PasswordInput.vue'
export default {
components: { EmailInput, PasswordInput, BaseButton },
data() {
return {
btnColor: 'indigo accent-2',
form: {
email: '',
password: ''
}
}
},
methods: {
async doLogin() {
try {
await this.$auth.loginWith("laravelSanctum", {
data: this.form,
})
this.$router.push('/')
} catch (e) {}
},
},
}
</script>
<style scoped>
.full-width {
width: 100%;
}
</style>
2. バリデーション実装
2-1. 各テキストフィールドに制約をつける
Vuetifyのv-text-field
にバリデーションを設定するには、バリデーション用関数をrules
属性に配列で渡します。
今回は、必須入力、文字数制限、メール形式入力のチェックをする関数を用意しました。
それぞれ下記のようなコードになります。
(value) => !!value || '必須項目なので値を入力してください。'
(value) => value.length <= 255 || '文字数をオーバーしています。'
(value) => {
const pattern =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return pattern.test(value) || '正しい形式で入力してください。'
}
入力された文字列がチェックを通ればtrue
を返し、通らなければエラー文字列を返します。
これらの関数をrules
属性に渡すことで、検証することができます。
修正後、最終的なコードは下記のようになりました。
EmailInput.vue(修正後)
<template>
<v-text-field
v-model="setEmail"
:rules="[rules.required, rules.email, rules.maxCount255]" //追加
label="メールアドレスを入力"
placeholder="your@email.com"
type="email"
outlined
dense
rounded
/>
</template>
<script>
export default {
props: {
email: {
type: String,
default: ''
}
},
//ここから追加
data() {
return {
rules: {
required: (value) => !!value || '必須項目なので値を入力してください。',
maxCount255: (value) =>
value.length <= 255 || '文字数をオーバーしています。',
email: (value) => {
const pattern =
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
return pattern.test(value) || '正しい形式で入力してください。'
}
}
}
},
//ここまで
computed: {
setEmail: {
get() {
return this.email
},
set(newVal) {
return this.$emit('update:email', newVal)
}
}
}
}
</script>
PasswordInput.vue(修正後)
<template>
<v-text-field
v-model="setPassword"
:rules="[rules.required, rules.minCount8]" //追加
type="password"
label="パスワードを入力"
placeholder="8文字以上"
outlined
rounded
dense
/>
</template>
<script>
export default {
props: {
password: {
type: String,
default: ''
}
},
//ここから追加
data() {
return {
rules: {
required: (value) => !!value || '必須項目なので値を入力してください。',
minCount8: (value) =>
value.length >= 8 || 'パスワードは8文字以上で入力してください。'
}
}
},
//ここまで
computed: {
setPassword: {
get() {
return this.password
},
set(newVal) {
return this.$emit('update:password', newVal)
}
}
}
}
</script>
2-2. フォーム全体をバリデーションチェック
現状で、各テキストフィールドに制約をつけることはできたが、不正値の入力があっても送信されてしまうと言う問題点があります。
そのために、コードを修正していきます。
まず、下記のようにv-form
にref
属性を付与してVue側からアクセスできるようにします。
<v-form ref="login_form">
//略
</v-form>
v-form
にref
を設定することで、validate()
にアクセスできるようになっています。
validate()
は、すべての要素がバリデーションを通過しているかを確認してくれるので、バリデーションをかけたいタイミングで呼びます。
修正後、最終的なコードは下記のようになりました。
pages/login.vue
<template>
<v-card max-width="500" class="mx-auto mt-5 full-width" flat outlined>
<v-card-title class="text-center pa-8">
<h1 class="text-h5 font-weight-bold full-width">ログイン情報入力</h1>
</v-card-title>
<v-divider> </v-divider>
<div class="px-6 py-8">
<div style="max-width: 336px" class="mx-auto">
<v-card-text>
<v-form ref="login_form" @submit.prevent="doLogin"> //ref属性で名前をつける
<email-input :email.sync="form.email" />
<password-input :password.sync="form.password" />
<v-card-actions>
<v-row justify="end" class="pb-8 pt-4">
<base-button :color="btnColor">ログイン</base-button>
</v-row>
</v-card-actions>
</v-form>
</v-card-text>
</div>
</div>
</v-card>
</template>
<script>
import BaseButton from '../../atoms/buttons/BaseButton.vue'
import EmailInput from '../../atoms/inputs/EmailInput.vue'
import PasswordInput from '../../atoms/inputs/PasswordInput.vue'
export default {
components: { EmailInput, PasswordInput, BaseButton },
data() {
return {
btnColor: 'indigo accent-2',
form: {
email: '',
password: ''
}
}
},
methods: {
async doLogin() {
if (this.$refs.login_form.validate()) { //追加
try {
await this.$auth.loginWith('laravelSanctum', {
data: this.form
})
this.$router.push('/')
} catch {}
} //追加
}
}
}
</script>
<style scoped>
.full-width {
width: 100%;
}
</style>
以上で実装完了となります。
3. 参考記事