
フロント側(vue)のバリデーションを実装したい!
どんな風に実装するのー?
記事は、こんな悩みに対して書きました。
この記事を書いている私は、
2020年1月現在メガベンチャーの社内スタートアップの部署でエンジニア(1年目)をしてます。
プログラミング未経験からメガベンチャーへの転職を成功させた経験・ノウハウ
Webエンジニアになってから学んだこと
をブログにまとめています。
前回の記事では、「バックエンド側(Laravel)のバリデーション」を紹介しましたが、
本記事では、「Vueでのバリデーション」にフォーカスしてソースコード付きで解説していきます。
目次
そもそもフロント側でのバリデーションは必要?
実際問題、
フロント側でバリデーションをしていなくても
サーバー側でバリデーションができていれば、
致命的な事故にはなりません。
ですが、サイトをきちんと作り込む上では
フロント側でのバリデーションは欠かせないでしょう。
理由としては、
ユーザーに親切なサイトになります。
サーバー側でバリデーションに引っかかる度に、画面遷移や更新してしまうと
軽快なサイトに慣れているユーザーにとってはストレスになってしまいます。
また、
フロント側でリクエストデータを制御してあげることで
無駄なリクエストが投げられることもなくなるので、
サーバーとの通信コストも下げることができます。
私は、メンターに口酸っぱく
「バリデーションはフロント側とサーバー側両方で必ずやること」
と言われているため、
もうフロント側でバリデーションをいれないと気持ち悪いですw
ということでフロント側(Vue)でバリデーションを実装していきます。
なにやら調べるとバリデーションのライブラリもあったのですが、
可読性、保守性を意識したコーディングの練習もかねて
ライブラリは使わないことにしました。
バリデーション実装(Vue)
まずは画面のソースコードからみてみましょう。
resources/views/tweet/index.blade.php
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="csrf-token" content="{{ csrf_token() }}">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<link rel="stylesheet" href="{{ mix('/css/tweet.css') }}">
</head>
<body>
<div id="tweet">
<header>
<div class="contents">
<section class="submit-form">
<input class="form" v-model.trim="tweet" :class="{'is-error': !canSubmit}">
<button class="btn" @click="storeTweet" :disabled="!canSubmit">送信</button>
<span v-if="!isValidated.tweet" v-text="validationErrorMessage.tweet" :class="{'is-error-message': !isValidated.tweet}"></span>
</section>
</div>
</header>
<main>
<div class="contents">
<ul>
@foreach ($tweets as $tweet)
<li>{{ $tweet->tweet }}</li>
@endforeach
</ul>
</div>
</main>
<footer>
</footer>
</div>
<script src="{{ mix('js/tweet.js') }}"></script>
</body>
</html>
header
タグ内をみてください。v-model
で入力内容を変数tweet
にバインディングし、
変数を監視することでバリデーションを行います。
以下のVueタグを用いてバリデーション結果を画面に反映していきます。v-if
でバリデーションメッセージの出し分け:disabled
は、ボタンの表示・非表示を制御:class
は、デザイン(CSS)の出し分け
具体的にバリデーション機能を実装している
JSの実装内容をみていきましょう。
resources/js/tweet.js
require('./csrf.js');
new Vue({
el: '#tweet',
data: {
tweet: '',
isValidated: {
tweet: false
},
validationConditions: {
max: 255
},
validationErrorMessages: {
max: "255文字以下で書いてください"
},
validationErrorMessage: {
tweet: null
},
canSubmit: false,
},
methods: {
storeTweet() {
this.preventDoubleClick();
this.postTweet();
},
preventDoubleClick() {
if (!this.canSubmit) {
return;
}
this.canSubmit = false;
},
postTweet() {
axios.post('/tweet', {
tweet: this.tweet
})
.then(function (response) {
this.tweet='';
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
},
watch: {
tweet: function(newTweet, oldTweet) {
if (this.tweet === '') {
this.canSubmit = false;
return;
}
if (this.tweet.length > this.validationConditions.max) {
this.validationErrorMessage.tweet = this.validationErrorMessages.max;
this.isValidated.tweet = false;
this.canSubmit = false;
return;
}
this.validationErrorMessage.tweet = null;
this.isValidated.tweet = true;
this.canSubmit = true;
return;
}
}
});
仕様を満たすように変数を設計します。
<仕様>
入力フォームが以下の条件を満たす時、枠の色が赤色かつ送信ボタンが非表示に
・空白の場合
・入力されている文字数が255文字以上の場合
<変数の役割>tweet
:入力フォームに入力されている文字を格納isValidated
:バリデーションを通っているかを判断validationConditions
:バリデーションの条件を管理validationErrorMessages
:バリデーションメッセージを管理validationErrorMessage
:画面表示するバリデーションメッセージを格納canSubmit
:送信可否を判断
仮にバリデーションの条件が増えた場合でも、validationConditions
とvalidationErrorMessages
に配列をプッシュすれば、バリデーション内容を管理しやすいです。
バリデーションのロジックは、watch
に実装します。
変数tweet
を監視。
変数が変化するごとにイベントが発火するので、
リアルタイムにバリデーションを行うことができます。
バリデーションに引っかかる場合は、リアルタイムにメッセージが表示され、
バリデーションを通る入力内容でのみ、送信ボタンが押せたほうが
ユーザーに優しいですよね^^
あとは、CSSを追加
resources/sass/_tweet_style.scss
.submit-form {
.is-error {
border-color: $red;
&-message {
color: $red;
}
}
}
JSをビルドして、
ローカルサーバー起動して確認します。
npm run dev
php artisan serve
以上で実装終了です!
まとめ
以上、フロント側Vueでの「バリデーション」の解説でした。
ユーザー体験がリッチなWebサイトが増えている昨今、
もはやフロント側もバリデーションをつけるのは、今や必須事項です。
是非とも、サーバー側だけでなくフロント側のバリデーションも
忘れずにいきましょう。
次回は、
「無限スクロール(Vueライブラリ使用)」
を解説します!
それでは、また!!