0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nuxt3とVuetify3を使ってフォームのバリデーションを作成する

Posted at

完成サンプル

たとえば、未入力のままREGISTER(登録)ボタンをクリックすると...
image.png

ページ上部にAlertメッセージの表示とバリデートチェックで引っかかった項目を赤字で表示するようにしてみます。
image.png

Vuetify3とは?

Vuetify3は、Vue3向けのUIフレームワークです。これらのUIフレームワークを使用することで統一感のあるデザインと開発工数を効率化を図ることができます。

今回は、Alert Componentを使って実装しています。

完成コード

まず菅聖子度をお見せします。

frontend/pages/navigation/nabigation.vue
<script setup lang="ts">
import { ref } from 'vue';
import { useField, useForm } from 'vee-validate';
import * as yup from 'yup';
import axios from 'axios';
import { useRouter } from 'vue-router';

const formRef = ref(null);
const { handleSubmit } = useForm();

const router = useRouter();

/*---Name validation---*/
const nameField = useField(
  'name',
  yup.string().required('Name must be required.').min(2, 'Please input over 1 character.')
);
const { value: name, errorMessage: nameerror } = nameField;

/*---Email validation---*/
const emailField = useField(
  'email',
  yup.string().required('Email must be required.').matches(/^[a-zA-Z0-9_\-]+(\.[a-zA-Z0-9_\-]+)*@([a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]\.)+[a-zA-Z]{2,}$/, { message: 'Mail address is invalid' })
);
const { value: email, errorMessage: emailerror } = emailField;

/*---Password validation---*/
const passwordField = useField(
  'password',
  yup.string().required('Password must be required.').min(2, 'Please input over 1 character.').max(11, 'The password is too long. Please input until 10 characters.')
);
const { value: password, errorMessage: passworderror } = passwordField;

/*---Gender validation---*/
const genderField = useField(
  'gender',
  yup.string().required('Gender must be required.')
);
const { value: gender, errorMessage: gendererror } = genderField;

/*---Survey validation---*/
const surveyField = useField<string[]>(
  'survey',
  yup.array().of(yup.string()).min(1, 'Please choose at least one.'),
  {initialValue:[]} // 配列の長さが1以上であることを確認
);
const { value: survey } = surveyField;

const nameErrorMessage = ref('');
const emailErrorMessage = ref('');
const passwordErrorMessage = ref('');
const genderErrorMessage = ref('');
const surveyErrorMessage = ref('');

/** Set alert bar on header */
const globalError = ref('');
const showAlert = ref(false);

/** Define formData validate flag */
const flagForValidate = ref(true);

const surveyOptions = [
  'I want to know from News letters', 
  'I want to know from Campaign', 
  'I want to know from Events'
];

const onSubmit = async()=>{

 try{
  /** Initialize validate flag. */
  flagForValidate.value = true;
  /** Hidden alert display */
  showAlert.value = false;
  /** Initialize error message */
  nameErrorMessage.value = '';
  emailErrorMessage.value = '';
  passwordErrorMessage.value = '';
  genderErrorMessage.value = '';
  surveyErrorMessage.value = '';

  /** Define FormData object */
  const formData = new FormData();

  /** Validate value of name if name is empty or not. */
  if(name.value === '' || name.value === undefined){
    nameErrorMessage.value = 'Please input your name.';
    /** Update value of flag */
    flagForValidate.value = false;
  }
  formData.append('name',name.value);

  /** Validate value of email if email is empty or not. */
  if(email.value === '' || email.value === undefined){
    emailErrorMessage.value = 'Please input your email.';
    /** Update value of flag */
    flagForValidate.value = false;
  }
  formData.append('email',email.value);

  /** Validate value of password if password is empty or not. */
  if(password.value === '' || password.value === undefined){
    passwordErrorMessage.value = 'Please input your password.';
    /** Update value of flag */
    flagForValidate.value = false;
  }
  formData.append('password',password.value);

  /** Validate value of gender if gender is empty or not. */
  if(gender.value === '' || gender.value === undefined){
    genderErrorMessage.value = 'Please input your gender.';
    /** Update value of flag */
    flagForValidate.value = false;
  }
  formData.append('gender',gender.value);

  /** Validate value of gender if gender is empty or not. */
  if(survey.value.length === 0 || survey.value === undefined){
    surveyErrorMessage.value = 'Please input your survey.';
    /** Update value of flag */
    flagForValidate.value = false;
  }

  /** Evaluate value of flag:if this is false,show alert message on header.*/
  if(!flagForValidate.value){
    showAlert.value = true;
    globalError.value = 'Invalide some values on the form.Please confirm and input data.';
    return;
  }

  formData.append('survey',JSON.stringify(survey.value));
  console.log('survey.value:', survey.value);
  console.log(...formData.entries());
  
  const response = await axios.post('http://localhost:8000/api/creategeneraluser/',formData);
  if(response.status === 201){
    alert('Sucess');
    console.log(response);
    router.push('/dashboard/dashboard');
  }else{
    alert('>>');
    
  }
 }catch(error){
  alert('error');
  console.log(error);
 }

}

//const router = useRouter();
const clickBackToTopPage = () => {
  router.push('/');
};
</script>

<template>
  <v-app>
    <v-alert
    v-if="showAlert"
    :text="globalError"
    type="error"
    title="Invalide Error"
    class="mt-2 mb-4"
    border="start"
    variant="tonal"
    color="error"
    icon="$error"
    prominent
  ></v-alert>
    <v-main>
      <v-container class="mt-5">
        <v-form @submit.prevent="onSubmit" ref="formRef">
          <!-- Name -->
          <v-text-field
            v-model="name"
            label="Name"
            required
          ></v-text-field>
          <span>{{ nameerror }}</span>
          <span style="color:red;">{{ nameErrorMessage }}</span>

          <!-- Mail Address -->
          <v-text-field
            v-model="email"
            label="Email"
            type="email"
            required
          ></v-text-field>
          <p>{{ emailerror }}</p>
          <span style="color:red;">{{ emailErrorMessage }}</span>

          <!-- Password -->
          <v-text-field
            v-model="password"
            label="Password"
            type="password"
            required
          ></v-text-field>
          <p>{{ passworderror }}</p>
          <span style="color:red;">{{ passwordErrorMessage }}</span>

          <!-- Gender (radio button) -->
          <v-radio-group
            v-model="gender"
            label="Sex"
            row
          >
            <v-radio label="man" value="man"></v-radio>
            <v-radio label="woman" value="woman"></v-radio>
            <v-radio label="other" value="other"></v-radio>
          </v-radio-group>
          <p>{{ gendererror }}</p>
          <span style="color:red;">{{ genderErrorMessage }}</span>
          <br/>
          <!-- Survey (checkboxes) -->
          <v-label>Survey</v-label>
          <v-row>
            <v-col cols="12" v-for="option in surveyOptions" :key="option">
              <v-checkbox
                :label="option"
                :value="option"
                v-model="survey"
                hide-details
              />
            </v-col>
          </v-row>
          <span style="color:red;">{{ surveyErrorMessage }}</span>
          <br/>
          <!--
          <v-selection-group v-model="survey" multiple>
            <v-checkbox
              v-for="option in surveyOptions"
              :key="option"
              :label="option"
              :value="option">
            </v-checkbox >
          </v-selection-group>
          <p>{{ surveyerror }}</p>
          -->

          <!-- Submit button -->
          <v-btn type="submit" color="primary" class="mr-4">Register</v-btn>
          <v-btn type="button" color="success" @click="clickBackToTopPage">BackToTopPage</v-btn>
        </v-form>
      </v-container>
    </v-main>
  </v-app>
</template>

コードの説明

Yupの導入

Yupは、バリデーションチェックを行うためのライブラリです。

Yupを使えば、バリデーションのカスタマイズを柔軟に行うことができます。

sample.vue
import * as yup from 'yup';

/*---Name validation---*/
const nameField = useField(
  'name',
  yup.string().required('Name must be required.').min(2, 'Please input over 1 character.')
);
const { value: name, errorMessage: nameerror } = nameField;

Vuetify3-Alert Componentsの導入

今回は、Registerボタンを押下してエラーを検知した時にページ上部にAlertメッセージを表示させます。
そのため、v-alertコンポーネントを使ってオブジェクトを作成しましょう。

sample.vue
//Set alert bar on header 
const globalError = ref('');
const showAlert = ref(false);

    <v-alert
    v-if="showAlert"
    :text="globalError"
    type="error"
    title="Invalide Error"
    class="mt-2 mb-4"
    border="start"
    variant="tonal"
    color="error"
    icon="$error"
    prominent
  ></v-alert>

const globalError = ref('');は、Alertメッセージの内容を埋め込むためのオブジェクトです。
const showAlert = ref(false);は、v-alertをBoolean値に応じて動的に制御するオブジェクトです。

各項目が空の場合のエラー表示

たとえば、v-modelの摂る双方向ばいディング値がnameの値が空の場合に<span />タグにエラーメッセージを表示する方法です。

sample.vue
const nameErrorMessage = ref('');

/** Validate value of name if name is empty or not. */
  if(name.value === '' || name.value === undefined){
    nameErrorMessage.value = 'Please input your name.';
    /** Update value of flag */
    flagForValidate.value = false;
  }
  formData.append('name',name.value);

ref使って初期化('')します。
バリデーションエラーがった場合は、メッセージをnameErrorMessage に入れるのですが上記のように入れます。

sample.vue
nameErrorMessage.value = 'Please input your name.';

誤ってnameErrorMessage = 'Please input your name.';としてしまうと直接文字列を代入 すると、Vue のリアクティビティが壊れます。これは ref オブジェクト自体を上書きしているためです。

以上です。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?