如何在 nuxtui 中使用 zod 验证输入的同时转换输入?

问题描述 投票:0回答:1

我在 Nuxt 项目中有这个表单

<template>
  <UCard>
    <template #header>
      <h3 class="font-semibold text-xl">Ajouter une personne</h3>
    </template>

    <UForm
      :schema="schema"
      :state="state"
      class="space-y-2"
      @submit="onSubmit"
    >
      <UFormGroup class="" label="Prénom" name="firstName">
        <UInput v-model="state.firstName" />
      </UFormGroup>

      <UFormGroup class="" label="Nom" name="lastName">
        <UInput v-model="state.lastName" />
      </UFormGroup>

      <UFormGroup class="" label="Email" name="email">
        <UInput v-model="state.email" />
      </UFormGroup>

      <UFormGroup class="" label="Téléphone" name="phone">
        <UInput v-model="state.phone" />
      </UFormGroup>

      <UFormGroup class="" label="Membre depuis" name="memberSince">
        <UInput v-model="state.memberSince" type="date" />
      </UFormGroup>

      <UFormGroup class="" label="Membre l'an dernier?" name="memberLastYear">
        <USelect v-model="state.memberLastYear" :options="mlyOptions" />
      </UFormGroup>
      <UButton type="submit"> Enregistrer cette personne </UButton>
    </UForm>
    <template #footer>
      <Placeholder class="h-8" />
    </template>
  </UCard>
</template>

<script setup lang="ts">
import type { FormError, FormSubmitEvent } from "#ui/types";
import { z } from 'zod'

const mlyOptions= ['Oui','Non']
const schema = z.object({
  firstName:z.string().regex(/^[ÈÉÊA-Z][a-zïèéê']*([\-\s]{1}[ÈÉÊA-Z]{1}[a-zïèéê]*)*$/,
  "Capitale en début de chaque prénom. Pas de double espace ou tiret. Pas d'espace ou de tiret en début et fin"), 
  lastName:z.string().regex(/^([ÈÉÊA-Z]){1}('[ÈÉÊA-Z]+){0,1}[a-zïèéê']*([\-\s]{1}[ÈÉÊA-Z]{1}[a-z'ïèéê]*)*$/,
  "Capitale en début de chaque nom. Pas de double espace ou tiret. Pas d'espace ou de tiret en début et fin. l'apostrophe des noms irlandais acceptée."),

 
  email: z.string().email("L'adresse électronique est mal formée"),
  phone:z.string().trim().min(10,"Le numéro de téléphone doit comprendre au moins 10 chiffres"),
  memberSince: z.coerce.date(),
  memberLastYear:z.string()
})

type Schema = z.output<typeof schema>

const state = reactive({
  firstName: undefined,
  lastName:undefined,
  email: undefined,
  phone: undefined,
  memberSince: undefined,
  memberLastYear: undefined

})
async function onSubmit(event: FormSubmitEvent<any>) {
  // Do something with data
  console.log("submit");
  console.log(toRaw(event.data));
}
</script>

我想检查电话号码是否以法语书写,即 xx xx xx xx xx(五对数字,以空格分隔。 为此,我可以编写一个正则表达式并像上面示例中的名字和姓氏一样使用它,并且仅当用户遵守规则时才接受输入。 但是如何对用户更加宽容,只要求他输入至少 10 位数字,而不管有多少个空格以及这些空格在字符串中的位置,然后使用转换来纠正

我试过了

  phone:z.string().trim().transform((val,ctx)=>{
    if(val.length!==10){
      ctx.addIssue({
      code: z.ZodIssueCode.custom,
      message: "You must enter 10 digits",
    })
    return z.NEVER;
  }
  var parts=val.match(/.{1,2}/g)
  return parts.join(' ')
  ),

这不起作用。单独事件trim(),即

phone:z.string().trim() 

什么都不做

nuxt.js zod
1个回答
0
投票

trim
只会删除前导和尾随空白(并且不会触及字符串中的空白)。您可以通过检查以下输出来亲自验证这一点:

import { z } from "zod";
console.log(z.string().trim().parse("  hi there   ")); // Logs "hi there"

请注意,字符串中心的

' '
字符仍然保留。要在转换步骤中删除字符串中的所有空格,您可以使用
String.prototype.replaceAll

const schema = z.string()
.trim()
.transform((s, ctx) => {
  const withoutWhitespace = s.replaceAll(/\s*/g, '');
    if (withoutWhitespace.length !== 10) {
      ctx.addIssue({
      code: z.ZodIssueCode.custom,
      message: "You must enter 10 digits",
    })
    return z.NEVER;
  }
  return withoutWhitespace;
});
console.log(schema.safeParse("12345678910")); // Logs a failure result
// The following parses successfully and strips out the whitespace.
console.log(schema.parse(" 0 1 2 3 4 5 6\n\r\t 7 8 9 "));

replaceAll
方法具有相当广泛的浏览器支持,尽管它仍然有些新。您可能需要针对您的具体用例咨询我可以使用这个吗? (如果您需要支持较旧的浏览器,例如 IE11,应该可以进行 polyfill)。您可能还需要更新 lib
 中的 
tsconfig
 选项以包含对其的支持。

© www.soinside.com 2019 - 2024. All rights reserved.