APIでは不正値が保存されないように必ずバリデーションを掛けますが、フロントは任意。
でも、あった方がユーザーが入力段階で気付けるのと、無駄なAPIリクエストを抑制できる。
フロントだけで完結できるものは追加した方が、親切&インフラに優しい。

vee-validateが使える状態になっている前提で記載します。

入力値のみでチェックする場合

ソースコードはこちら
https://dev.azure.com/nightonly/nightonly-app/_git/nightonly-nuxt/commit/4222dec2b847d0af209ca9ee3dbce2755445f89a?path=/components/send_settings/Index.vue

サブドメイン

<template>内

<validation-provider
  v-slot="{ errors }"
  name="slack_name"
  rules="required|max:32|subdomain"
>

<script>内

extend('subdomain', {
  message: '英字(小文字)・数字・ハイフンのみで入力してください。',
  validate (value) {
    return value == null || value === '' || value.match(/^[a-z0-9-]*$/) != null
  }
})

SlackのWebhook URL

https://hooks.slack.com/services/(半角英数字)/(半角英数字)/(半角英数字)
こんな感じのなのですが、将来の変更も想定して、ある程度汎用的なLチェックにしました。

<template>内

<validation-provider
  v-slot="{ errors }"
  name="slack_webhook_url"
  rules="required|max:128|webhook_url"
>

<script>内

extend('webhook_url', {
  message: '形式が正しくありません。',
  validate (value) {
    return value == null || value === '' || value.match(/^https?:\/\/[A-Za-z0-9.-]+\/[A-Za-z0-9/]+$/) != null
  }
})

完全に汎用的にするには、記号も必要になりますが、今回は要件を絞って、ドメインは変わる事があるけど、パス複数ありで半角英数字のみとしました。

Slackのメンション

任意で、下記のいずれかを入力させます。
> !channel または !here または !subteam^ID または @メンバーID

<template>内

<validation-provider
  v-slot="{ errors }"
  name="slack_mention"
  rules="max:64|slack_mention"
>

<script>内

extend('slack_mention', {
  message: '形式が正しくありません。',
  validate (value) {
    return value == null || value === '' || value.match(/^[A-Za-z0-9!^@|]*$/) != null
  }
})

他の入力値と比較する場合

ソースコードはこちら
https://dev.azure.com/nightonly/nightonly-app/_git/nightonly-nuxt/commit/4222dec2b847d0af209ca9ee3dbce2755445f89a?path=/components/tasks/InputTask.vue

開始日・終了日

<template>内

<validation-provider
  v-slot="{ errors }"
  name="started_date"
  rules="required|before_started_date:ended_date"
>

<validation-provider
  v-slot="{ errors }" 
 name="ended_date"
  rules="after_ended_date:started_date"
>

<script>内

extend('before_started_date', {
  params: [{
    name: 'endValue',
    isTarget: true
  }],
  message: '終了日よりも前の日付を入力してください。',
  validate (value, { endValue }) {
    return value == null || value === '' || endValue == null || endValue === '' || new Date(value) < new Date(endValue)
  }
})
extend('after_ended_date', {
  params: [{
    name: 'startValue',
    isTarget: true
  }],
  message: '開始日より後の日付を入力してください。',
  validate (value, { startValue }) {
    return value == null || value === '' || startValue == null || startValue === '' || new Date(startValue) < new Date(value)
  }
})

終了日のみにすると、開始日を変更しても終了日のルールが動かない場合がるので、両方に入れました。

今日より後

元の値のままの場合はOKで、変更する時のみチェックしたい場合、

<template>内(先ほどの修正)

 <validation-provider
   v-slot="{ errors }"
   name="started_date"
-   rules="required|before_started_date:ended_date">
+   :rules="`required${syncTask.started_date != taskStartedDate ? '|after_today_date' : ''}|before_started_date:ended_date`"
   >

rulesに設定するかの条件を入れればOK

<script>内

extend('after_today_date', {
  message: '今日より後の日付を入力してください。',
  validate (value) {
    return value == null || value === '' || new Date() <= new Date(`${value}T23:59:59`)
  }
})

この中では、thisの値を参照できない。スコープ違うの当然ですね。

入力しない値と比較する場合

ソースコードはこちら
https://dev.azure.com/nightonly/nightonly-app/_git/nightonly-nuxt/commit/76edcc73909f976b41e07ff92afed009ffef803b?path=/components/tasks/InputEvent.vue

開始以降、翌月末まで

<template>内

<validation-provider name="start">
  <v-text-field v-model="syncEvent.start" type="hidden" />
</validation-provider>
<validation-provider
  v-slot="{ errors }"
  name="last_ended_date"
  rules="required|after_end_date:start|before_end_date:start">

thisの値を参照できないので、hiddenで値を渡してあげる。
そうすれば、他の入力値と比較する場合と同じように値を渡せます。

<script>内

import { addMonths, endOfMonth } from 'date-fns'

extend('after_end_date', {
  params: [{
    name: 'startValue',
    isTarget: true
  }],
  message: '開始以降の日付を入力してください。',
  validate (value, { startValue }) {
    return value == null || value === '' || startValue == null || startValue === '' || new Date(value) >= new Date(startValue)
  }
})
extend('before_end_date', {
  params: [{
    name: 'startValue',
    isTarget: true
  }],
  message: '翌月末までの日付を入力してください。',
  validate (value, { startValue }) {
    return value == null || value === '' || startValue == null || startValue === '' || new Date(value) <= endOfMonth(addMonths(new Date(startValue), 1))
  }
})

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です