Vee-validate 对来自 primevue 的数字和复杂输入进行验证

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

我刚刚开始第一次一起使用 PrimeVue 和 VeeValidate,我正在为两种情况而苦苦挣扎。

  • 验证
    InputNumber
    ,我尝试添加一个
    v-bind
    数字,但是当我点击离开时该字段被清除,不确定这里发生了什么
  • 验证
    Dropdown
    MultiSelect
    ,它们分别是键/值对对象和键/值对对象数组,我似乎也无法验证它们。我什至无法在组件中正确选择数据...我尝试了 v-bind 和 v-model 但无法让它工作。

我错过了什么?

<script setup lang="ts">
import { Form, Field } from 'vee-validate';
import { PropType } from 'vue';
import Button from 'primevue/button';
import InputText from 'primevue/inputtext';
import InputNumber from 'primevue/inputnumber';
import Textarea from 'primevue/textarea';
import Dropdown from 'primevue/dropdown';
import MultiSelect from 'primevue/multiselect';
import * as yup from 'yup';
import { categoryToLabel, availabilityToLabel } from '@/helpers/dishes';
import { useRouter } from 'vue-router';
import { Dish, DishCategory, DishAvailability } from '@/types/Dish';
import { createOrUpdateDish } from '@/api/Dish';
const router = useRouter();

const { dish } = defineProps({
  // Optional - Dish to update
  dish: {
    type: Object as PropType<Dish>,
  },
});

const initialValues = {
  name: dish?.name || '',
  description: dish?.description || '',
  price: dish?.price || null,
  category: dish?.category
    ? {
        name: categoryToLabel.get(dish.category),
        value: dish.category,
      }
    : {},
  availability: dish?.availability
    ? dish.availability.map((availability) => ({
        name: availabilityToLabel.get(availability),
        value: availability,
      }))
    : [],
  waitingTime: dish?.waiting_time || null,
};

const schema = yup.object({
  name: yup.string().required(),
  description: yup.string().required(),
  price: yup.number().required().positive().integer(),
  category: yup.object().shape({ name: yup.string(), value: yup.string() }),
  availability: yup.array().required().min(1),
  waitingTime: yup.number().required().positive().integer(),
});

const categoryOptions = ['starter', 'main_course', 'dessert', 'beverage'].map(
  (category: DishCategory) => ({
    name: categoryToLabel.get(category),
    value: category,
  })
);

const availabilityOptions = [
  'breakfast',
  'lunch',
  'dinner',
  'weekdays',
  'weekends',
].map((availability: DishAvailability) => ({
  name: availabilityToLabel.get(availability),
  value: availability,
}));

const onCancelClicked = () => {
  router.push('/');
};

const onFormSubmitted = async (values: typeof initialValues) => {
  console.log('values :>> ', JSON.stringify(values, null, 2));
};
</script>

<template>
  <div class="max-width-container dish-creation">
    <h2 class="title">Dish {{ dish ? 'update' : 'creation' }} form</h2>

    <Form
      class="form"
      :initial-values="initialValues"
      :validation-schema="schema"
      @submit="onFormSubmitted"
    >
      <Field name="name" v-slot="{ field, errorMessage }">
        <div class="form__row">
          <label for="name">Name</label>
          <InputText
            v-bind="field"
            aria-describedby="name-help"
            :class="{ 'p-invalid': errorMessage }"
          />
          <small id="name-help" class="p-error">{{ errorMessage }}</small>
        </div>
      </Field>

      <Field name="description" v-slot="{ field, errorMessage }">
        <div class="form__row">
          <label for="description">Description</label>
          <Textarea
            id="description"
            v-bind="field"
            autoResize
            rows="5"
            cols="30"
            aria-describedby="descripition-help"
            :class="{ 'p-invalid': errorMessage }"
          />
          <small id="description-help" class="p-error">{{
            errorMessage
          }}</small>
        </div>
      </Field>

      <Field name="price" v-slot="{ field, errorMessage }">
        <div class="form__row">
          <label for="price">Price</label>
          <InputNumber
            id="price"
            v-bind:number="field"
            inputId="withoutgrouping"
            :useGrouping="false"
            :class="{ 'p-invalid': errorMessage }"
            aria-describedby="price-help"
          />
          <small id="price-help" class="p-error">{{ errorMessage }}</small>
        </div>
      </Field>

      <Field name="category" v-slot="{ value, errorMessage, handleChange }">
        <div class="form__row">
          <label for="category">Category</label>
          <Dropdown
            @update:model-value="handleChange"
            :model-value:="value"
            :options="categoryOptions"
            id="category"
            optionLabel="name"
            optionValue="value"
            placeholder="Category"
            aria-describedby="category-help"
            :class="{ 'p-invalid': errorMessage }"
          />
        </div>
      </Field>

      <Field name="availability" v-slot="{ value, errorMessage, handleChange }">
        <div class="form__row">
          <label for="availability">Availability</label>
          <MultiSelect
            @update:model-value="handleChange"
            :model-value:="value"
            :maxSelectedLabels="3"
            :options="availabilityOptions"
            optionLabel="name"
            placeholder="Availability"
            :class="{ 'p-invalid': errorMessage }"
          />
        </div>
      </Field>

      <Field name="waitingTime" v-slot="{ field, errorMessage }">
        <div class="form__row">
          <label for="waiting-time">Waiting time (in mins)</label>
          <InputNumber
            id="waiting-time"
            v-bind:number="field"
            inputId="withoutgrouping"
            :useGrouping="false"
            aria-describedby="waiting-time-help"
            :class="{ 'p-invalid': errorMessage }"
          />
          <small id="waiting-time-help" class="p-error">{{
            errorMessage
          }}</small>
        </div>
      </Field>

      <div class="form__row">
        <Button
          type="button"
          label="Cancel"
          severity="secondary"
          icon="pi pi-times"
          iconPos="right"
          @click="onCancelClicked"
          raised
        />
        <Button
          type="submit"
          :label="dish ? 'Update' : 'Create'"
          icon="pi pi-check"
          iconPos="right"
          raised
        />
      </div>
    </Form>
  </div>
</template>
javascript typescript vue.js vee-validate primevue
1个回答
0
投票

也在寻找如何做到这一点的答案(示例)。

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