Vue.jsでフォームを検証する方法

提供:Dev Guides
移動先:案内検索

序章

フォーム検証は、フォームフィールド検証とも呼ばれ、ユーザーがWebフォームのすべての必須フィールドに入力することを保証します。 フィールドに無効な値がある場合、エラーメッセージが表示され、値がすべてのルールを満たすまでフォームの送信が妨げられます。

テンプレート駆動型検証は、ディレクティブを使用して検証ルールをフォーム要素に直接設定するフォーム検証の一種です。

テンプレート駆動型の検証をVue.jsに実装するには、VeeValidateを使用できます。 VeeValidateは、入力フィールドを検証してエラーを表示できるようにするVue.jsのプラグインです。

これは、このチュートリアルで作成するもののアニメーション画像です。

このチュートリアルの最後に、VeeValidateを使用して入力フィールドを検証する登録フォームがあります。

前提条件

このチュートリアルは、JavaScriptの文字列とオブジェクトの知識があることを前提としています。 Vueにある程度精通していると有益ですが、必須ではありません。 Javascriptの詳細については、Javascriptでコーディングする方法シリーズをご覧ください。

さまざまなクラウドホストライブラリへの参照を含む単一のローカルHTMLファイルの構築に焦点を当てます。 @vue/cliを使用してVueプロジェクトを作成し、パッケージマネージャーを使用してvee-validateをインストールすることができます。 ただし、そのアプローチはこのチュートリアルの範囲外です。

ステップ1—VeeValidateを使用してVue.jsプロジェクトを設定する

Vue.jsフレームワークとVeeValidateライブラリが必要になります。

まず、端末を使用してregister.htmlという名前の新しいファイルを作成します。

nano register.html

そして、ウェブページの初期コードを追加します。

register.html

<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Vue Template Form Validation</title>
</head>
<body>

  <!-- ... -->

</body>
</html>

Vue.jsのブラウザービルドは、cdnjsから入手できます。 VeeValidateのブラウザビルドは、jsdelivrから入手できます。 register.htmlファイルの<body>に両方を追加します。

register.html

<body>

  <!-- include the Vue.js framework -->
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>

  <!-- include the VeeValidate library -->
  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vee-validate.min.js"></script>

</body>

これらのファイルは、CDN(コンテンツ配信ネットワーク)によって提供されます。 ローカルにダウンロードまたは保存するものはありません。

これで、Vue.jsとVeeValidateの最新の安定したバージョン(この記事の執筆時点)を使用する準備ができたWebページができました。

BootstrapとFontAwesomeの追加

スタイリングを確立するには、Bootstrapを使用できます。 図像を追加するには、 FontAwesomeを利用することもできます。

BootstrapおよびFontAwesomeのブラウザビルドは、BootstrapCDNから入手できます。 register.htmlファイルの<head>に両方を追加します。

register.html

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1.0">
  <title>Vue Template Form Validation</title>

  <!-- include the Bootsrap framework -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">

  <!-- include Font Awesome -->
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
</head>

この時点で、Vue、VeeValidate、Bootstrap、およびFontAwesomeがあります。 次に、検証するフォームを作成します。

フォームマークアップの作成

このサンプルフォームは、ユーザーから5つの情報を求めます。 nameemailusernamepassword、およびpassword_confirmationが必要になります。

まず、フォームの初期マークアップを、<script>タグの前のregister.htmlファイルの<body>に追加します。

register.html

<body>
  <div class="container my-3">
    <div class="row justify-content-around">
      <div class="col-6 rounded shadow">
        <h1 class="py-3">Sign up once and watch any of our free demos.</h1>
        <div id="signup-form">
          <form>

          <!-- ... form fields ... -->

          </form>
        </div>
      </div>
    </div>
  </div>

  <!-- ... library script tags ... -->
</body>

このコードは、空の<form>を確立し、レイアウトと外観にいくつかのBootstrapユーティリティを使用します。

次に、フォームフィールドを<form>に追加します。 nameのフィールドから始めます。

register.html

<form>

  <div class="form-group">
    <label for="name">Your Name</label>
    <div class="input-group">
      <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-user" aria-hidden="true"></i></span></span>
      <input type="text" id="name" name="name" placeholder="Name" class="form-control" />
    </div>
  </div>

</form>

このコードは、name用の<label>fa-user用のFontAwesomeアイコン、およびname用の<input>を作成します。

他の情報(emailusernamepassword、およびpassword_confirmation)についても、<form>に同様の追加を行うことができます。

register.html

<form>

  <!-- ... name ... -->

  <div class="form-group">
    <label for="email">Your Email</label>
    <div class="input-group">
      <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-envelope" aria-hidden="true"></i></span></span>
      <input type="email" id="email" name="email" placeholder="[email protected]" class="form-control" />
    </div>
  </div>

  <div class="form-group">
    <label for="username">Username</label>
    <div class="input-group">
      <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-users" aria-hidden="true"></i></span></span>
      <input type="text" id="username" name="username" placeholder="Enter your username" class="form-control" />
    </div>
  </div>

  <div class="form-group">
    <label for="password">Password</label>
    <div class="input-group">
      <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-lock" aria-hidden="true"></i></span></span>
      <input type="password" id="password" name="password" placeholder="Enter a password" class="form-control" />
    </div>
  </div>

  <div class="form-group">
    <label for="password_confirmation">Confirm Password</label>
    <div class="input-group">
      <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-lock" aria-hidden="true"></i></span></span>
      <input type="password" id="password_confirmation" name="password_confirmation" placeholder="Re-type password" class="form-control" />
    </div>
  </div>

</form>

このコードは、<label>、Font Awesomeアイコン、および<input>を作成します。 各入力には、固有のidおよびnameがあります。

<form>を完了するための登録ボタンを追加します:

register.html

<form>

  <!-- ... form fields ... -->

  <div class="form-group">
    <button type="submit" class="btn btn-block btn-lg btn-primary">Register</button>
  </div>

</form>

このコードは、ブートストラップスタイルを使用して大きな送信ボタンを作成します。

ウェブブラウザでregister.htmlを開いて、アプリの進行状況を確認できます。

ステップ2—Vueインスタンスの作成とマウント

次に、Vueインスタンスを作成し、#signup-formにマウントします。

<body>の最後に新しい<script>タグを追加し、signupFormを定義します。

register.html

<body>
  <!-- ... form ... -->
  <!-- ... library script tags ... -->

  <script>
    const signupForm = new Vue({
      el: '#signup-form'
    });
  </script>
</body>

dataオブジェクトにプロパティを追加します。

register.html

<body>
  <!-- ... form ... -->
  <!-- ... library script tags ... -->

  <script>
    const signupForm = new Vue({
      el: '#signup-form',
      data: {
        name: '',
        email: '',
        username: '',
        password: '',
        password_confirmation: ''
      }
    });
  </script>
</body>

次に、各フィールドのv-modelでプロパティを参照します。

nameフィールドに、以下を追加します。

register.html

<input type="text" id="name" name="name" placeholder="Name" class="form-control" v-model="name" />

emailフィールドに、以下を追加します。

register.html

<input type="email" id="email" name="email" placeholder="[email protected]" class="form-control" v-model="email" />

usernameフィールドに、以下を追加します。

register.html

<input type="text" id="username" name="username" placeholder="Enter your username" class="form-control" v-model="username" />

passwordフィールドに、以下を追加します。

register.html

<input type="password" id="password" name="password" placeholder="Enter a password" class="form-control" v-model="password" />

最後に、password_confirmationフィールドに、以下を追加します。

register.html

<input type="password" id="password_confirmation" name="password_confirmation" placeholder="Re-type password" class="form-control" v-model="password_confirmation" />

この時点で、nameemailusernamepassword、およびpassword_confirmationのモデルを持つVueインスタンスがあります。

ステップ3—ValidationObserverValdiationProviderを追加します

次に、ValidationObserverValidationProviderを登録する必要があります。

<body>の最後にある新しい<script>タグに両方を追加できます。

register.html

<body>
  <!-- ... form ... -->
  <!-- ... library script tags ... -->

  <script>
    Vue.component('validation-observer', VeeValidate.ValidationObserver);

    Vue.component('validation-provider', VeeValidate.ValidationProvider);
  </script>

  <!-- ... vue instance script tag ... -->
</body>

これで、<validation-observer>を使用して、<form>全体をラップできます。 また、<validation-provider>を使用して、フィールドを折り返すことができます。

register.html

<validation-observer>

  <form>

    <div class="form-group">
      <validation-provider>
        <label for="name">Your Name</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-user" aria-hidden="true"></i></span></span>
          <input type="text" id="name" name="name" placeholder="Name" class="form-control" v-model="name" />
        </div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider>
        <label for="email">Your Email</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-envelope" aria-hidden="true"></i></span></span>
          <input type="email" id="email" name="email" placeholder="[email protected]" class="form-control" v-model="email" />
        </div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider>
        <label for="username">Username</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-users" aria-hidden="true"></i></span></span>
          <input type="text" id="username" name="username" placeholder="Enter your username" class="form-control" v-model="username" />
        </div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider>
        <label for="password">Password</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-lock" aria-hidden="true"></i></span></span>
          <input type="password" id="password" name="password" placeholder="Enter a password" class="form-control" v-model="password" />
        </div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider>
        <label for="password_confirmation">Confirm Password</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-lock" aria-hidden="true"></i></span></span>
          <input type="password" id="password_confirmation" name="password_confirmation" placeholder="Re-type password" class="form-control" v-model="password_confirmation" />
        </div>
      </validation-provider>
    </div>

    <div class="form-group">
      <button type="submit" class="btn btn-block btn-lg btn-primary">Register</button>
    </div>

  </form>

</validation-observer>

これで、<validation-observer><valdiation-provider>で作成されたフォームができました。

ステップ4—VeeValidateルールの使用

VeeValidateルールは、1つ以上のフィールドに入力できるものに制限または条件を設定します。 検証が必要なフィールドを含むレコードを更新すると、検証ルールがチェックされます。 ルールに違反すると、トラップ可能なエラーが発生します。

たとえば、requiredバリデーターを使用できます。

<validation-provider rules="required">

パイプ文字(|)で区切られた複数の検証に合格できます。

たとえば、requiredおよびemailバリデーターを使用できます。

<validation-provider rules="required|email">

または、オブジェクトを渡して柔軟性を高めることもできます。

<validation-provider :rules="{ required: true, email: true, regex: /[0-9]+/ }">

これで、入力が変更されるたびに、バリデーターは検証のリストを左から右に実行し、入力が検証に失敗するたびにエラーヘルパーオブジェクトにデータを入力します。

このチュートリアルを書いている時点で、VeeValidateにはフォーム検証用の 30のルールがあり、独自のルールを作成するオプションがあります。

ルールの適用

次に、VeeValidateRulesをインポートする必要があります。

register.htmlファイルの<body>の最後にある新しい<script>タグに追加できます。

register.html

<body>
  <!-- ... form ... -->
  <!-- ... library script tags ... -->

  <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/rules.umd.js"></script>

  <!-- ... vue instance tags ... -->
</body>

次に、ルールをループして、すべてを使用可能にすることができます。

register.html

<body>
  <!-- ... form ... -->
  <!-- ... library script tags ... -->

  <script>
    Object.keys(VeeValidateRules).forEach(rule => {
      VeeValidate.extend(rule, VeeValidateRules[rule]);
    });
  </script>

  <!-- ... vue instance tags ... -->
</body>

そして、すべての入力にrequiredルールを適用します。

register.html

<validation-provider rules="required">

複数のルールを適用する

emailの場合、有効な電子メールアドレスのルールも適用します。

register.html

<validation-provider rules="required|email">

passwordの場合、6文字の最小長のルールも適用します。

register.html

<validation-provider rules="required|min:6">

これで、フィールドにrequiredemail、およびminのルールが設定されました。

クロスフィールド検証の適用

password_confirmationの場合、有効にするにはpasswordの値と一致する必要があります。 これを実現するには、ValidationObserverを使用します。これにより、password_confirmationpasswordを認識できるようになります。

vidpasswordフィールドに追加して、password_confirmedにターゲットを設定します。

register.html

<validation-provider rules="required|min:6" vid="password">

confirmedルールをpassword_confirmationフィールドに追加して、password_confirmedがその値をpasswordの値と比較するようにします。

register.html

<validation-provider rules="required|confirmed:password">

これで、フィールドにrequiredemailmin、およびconfirmedのルールが設定されました。

カスタムルールの追加

VeeValidateを使用すると、extendおよびvalidateを使用してカスタム検証ルールとメッセージを作成できます。

ユーザーが制限された単語で登録できないようにするルールを追加します。 この例では、ユーザーがadminpassword、およびadministratorという単語を使用することを制限します。

register.html

<body>
  <!-- ... form ... -->
  <!-- ... library script tags ... -->

  <script>
    // Declare an array of usernames that are invalid.
    const restricted_usernames = [
      'admin',
      'password',
      'administrator'
    ];

    // Extend the custom rule.
    VeeValidate.extend('checkuser', {
      name: 'Restricted Usernames',
      validate: value => {
        return restricted_usernames.includes(value.toLowerCase()) ? false : !! value
      },
      message: 'That {_field_} is unavailable.',
    });
  </script>

  <!-- ... vue instance tags ... -->
</body>

カスタムルールをusernameフィールドに追加します。

register.html

<validation-provider rules="required|checkuser">

これで、フィールドにrequiredemailminconfirmed、およびcheckuserのルールが設定されました。 ルールがすべて確立され、エラーメッセージの表示を開始できるようになりました。

ステップ5—VeeValidateエラーとフラグへのアクセス

VeeValidateではerrorsを利用できます。 VeeValidateには、状態情報用の複数のフラグもあります。 これらには、Vueのv-slotを使用してアクセスできます。

また、Vueのv-showを使用してVeeValidateエラーメッセージを表示し、Bootstrapのinvalid-feedbackクラスを使用してエラーのスタイルを設定します。

さらに、dirtyvalid、およびinvalidのVeeValidateフラグを、Vueのv-bind:classおよびBootstrapのis-validおよびis-invalidフィールドをスタイリングするためのクラス:

register.html

<validation-observer>

  <form>

    <div class="form-group">
      <validation-provider rules="required|alpha" v-slot="{ dirty, valid, invalid, errors }">
        <label for="name">Your Name</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-user" aria-hidden="true"></i></span></span>
          <input type="text" id="name" name="name" placeholder="Name" class="form-control" v-model="name" v-bind:class="{ 'is-valid': dirty && valid, 'is-invalid': dirty && invalid }" />
        </div>
        <div class="invalid-feedback d-inline-block" v-show="errors">{{ errors[0] }}</div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider rules="required|email" v-slot="{ dirty, valid, invalid, errors }">
        <label for="email">Your Email</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-envelope" aria-hidden="true"></i></span></span>
          <input type="email" id="email" name="email" placeholder="[email protected]" class="form-control" v-model="email" v-bind:class="{ 'is-valid': dirty && valid, 'is-invalid': dirty && invalid }" />
        </div>
        <div class="invalid-feedback d-inline-block" v-show="errors">{{ errors[0] }}</div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider rules="required|checkuser" v-slot="{ dirty, valid, invalid, errors }">
        <label for="username">Username</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-users" aria-hidden="true"></i></span></span>
          <input type="text" id="username" name="username" placeholder="Enter your username" class="form-control" v-model="username" v-bind:class="{ 'is-valid': dirty && valid, 'is-invalid': dirty && invalid }" />
        </div>
        <div class="invalid-feedback d-inline-block" v-show="errors">{{ errors[0] }}</div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider rules="required|min:6" vid="password" v-slot="{ dirty, valid, invalid, errors }">
        <label for="password">Password</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-lock" aria-hidden="true"></i></span></span>
          <input type="password" id="password" name="password" placeholder="Enter a password" class="form-control" v-model="password" v-bind:class="{ 'is-valid': dirty && valid, 'is-invalid': dirty && invalid }" />
        </div>
        <div class="invalid-feedback d-inline-block" v-show="errors">{{ errors[0] }}</div>
      </validation-provider>
    </div>

    <div class="form-group">
      <validation-provider rules="required|confirmed:password" v-slot="{ dirty, valid, invalid, errors }">
        <label for="password_confirmation">Confirm Password</label>
        <div class="input-group">
          <span class="input-group-prepend"><span class="input-group-text"><i class="fa fa-lock" aria-hidden="true"></i></span></span>
          <input type="password" id="password_confirmation" name="password_confirmation" placeholder="Re-type password" class="form-control" v-model="password_confirmation" v-bind:class="{ 'is-valid': dirty && valid, 'is-invalid': dirty && invalid }" />
        </div>
        <div class="invalid-feedback d-inline-block" v-show="errors">{{ errors[0] }}</div>
      </validation-provider>
    </div>

    <div class="form-group">
      <button type="submit" class="btn btn-block btn-lg btn-primary">Register</button>
    </div>

  </form>

</validation-observer>

この時点で、dirtyvalidinvalid、およびerrorsにアクセスできます。 関連するフィールドの下にフィードバックとしてエラーメッセージを表示するロジックを追加しました。 フィールドが相互作用して無効な場合、Bootstrapのis-invalidクラスが適用されます。 フィールドが相互作用して有効な場合、Bootstrapのis-validクラスが適用されます。

次のステップでは、フォームの送信を処理します。

ステップ6—フォーム送信の処理

VeeValidateは、ValidationObserverおよびhandleSubmit関数のinvalidフラグも提供します。 これらには、Vueのv-slotを使用してアクセスできます。

register.html

<validation-observer v-slot="{ invalid, handleSubmit }">

Vueのイベント修飾子を使用して、@submit.preventでフォーム送信をキャプチャします。 また、VeeValidateのhandleSubmitを使用して、すべてのフィールドが有効になるまでフォームの送信を防止します。

register.html

<form @submit.prevent="handleSubmit(onSubmit)">

これにより、onSubmitが呼び出されます。これは、console.logメッセージとして定義できます。

register.html

<script>
  const signupForm = new Vue({
    el: '#signup-form',
    data: {
      name: '',
      email: '',
      username: '',
      password: '',
      password_confirmation: ''
    },
    methods: {
      onSubmit: function() {
        console.log('Form has been submitted!');
      }
    }
  });
</script>

<button>disabled状態に保ち、フィールドがinvalidのときに情報を送信しないようにします。

register.html

<button type="submit" class="btn btn-block btn-lg btn-primary" v-bind:disabled="invalid">Register</button>

この時点で、Webブラウザでregister.htmlを開き、フォームを操作して検証をテストできます。

結論

このチュートリアルでは、テンプレート駆動型アプローチを使用してフォーム入力を検証する方法を示しました。 VeeValidateを使用すると、既存のルールを使用してフォーム入力を検証し、新しいルールを拡張し、エラーを表示し、フォーム送信を処理できます。

Vue.jsの詳細については、Vue.jsトピックページで演習とプログラミングプロジェクトを確認してください。