自定义组件绑定到primevue的from组件

30 阅读1分钟

image.png

父组件:

<template>
  <div class="card flex justify-center">
    <Form
      :resolver
      @submit="onFormSubmit"
      class="flex flex-col gap-4 w-full sm:w-56"
    >
      <FormField
        v-slot="$field"
        name="username"
        initialValue=""
        class="flex flex-col gap-1"
      >
        <input
          type="text"
          placeholder="Username"
          :class="[{ error: $field?.invalid }]"
          v-bind="$field.props"
        />
        <Message
          v-if="$field?.invalid"
          severity="error"
          size="small"
          variant="simple"
          >{{ $field.error?.message }}
        </Message>
      </FormField>
      <FormField
        v-slot="$field"
        name="password"
        initialValue="PrimeVue"
        class="flex flex-col gap-1"
      >
        <input
          v-model="$field.value"
          type="password"
          placeholder="Password"
          :class="[{ error: $field?.invalid }]"
          @input="$field.onInput"
          @blur="$field.onBlur"
          @change="$field.onChange"
        />
        <Message
          v-if="$field?.invalid"
          severity="error"
          size="small"
          variant="simple"
          >{{ $field.error?.message }}
        </Message>
      </FormField>

      <FormField v-slot="$field" name="testbind" initialValue="PrimeVu111e">
        testbind 当前值:{{ $field.value }}
        <!-- ✅ 正确绑定 -->
        <TestBind :value="$field.value" v-bind="$field.props" />
        <Message
          v-if="$field?.invalid"
          severity="error"
          size="small"
          variant="simple"
          >{{ $field.error?.message }}
        </Message>
      </FormField>

      <FormField v-slot="$field" name="testmodel" initialValue="PrimeVu111e">
        testmodel 当前值:{{ $field.value }}
        <p>使用props 接受value</p>
        <!-- ✅ 正确绑定 -->
        <TestModel v-model="$field.value" @input="$field.onInput" />
        <Message
          v-if="$field?.invalid"
          severity="error"
          size="small"
          variant="simple"
          >{{ $field.error?.message }}
        </Message>
      </FormField>

      <FormField v-slot="$field" name="testmodel2" initialValue="PrimeVu111e">
        testmodel2 当前值:{{ $field.value }}
        <p>使用definedmodel</p>
        <!-- ✅ 正确绑定 -->
        <TestModel v-model="$field.value" @input="$field.onInput" />
        <Message
          v-if="$field?.invalid"
          severity="error"
          size="small"
          variant="simple"
          >{{ $field.error?.message }}
        </Message>
      </FormField>
      <Button type="submit" severity="secondary" label="Submit" />
    </Form>

    {{ tesst1 }}
  </div>
</template>

<script setup>
import { reactive, ref } from 'vue';
import { zodResolver } from '@primevue/forms/resolvers/zod';
import { z } from 'zod';
import { useToast } from 'primevue/usetoast';
import TestBind from '@/components/TestBind.vue';
import TestModel from '@/components/TestModel.vue';
const toast = useToast();
const tesst1 = ref();
const resolver = zodResolver(
  z.object({
    username: z.string().min(1, { message: 'Username is required.' }),
    password: z.string().min(1, { message: 'Password is required.' }),
    testbind: z.string(),
    testmodel: z.string(),
    testmodel2: z.string(),
  })
);

const onFormSubmit = (res) => {
  console.log(res);
  console.log(res.values);

  if (res.valid) {
    toast.add({
      severity: 'success',
      summary: 'Form is submitted.',
      life: 3000,
    });
  }
};
</script>

子组件:

<template>
  <div>
    <div>{{ model }}</div>
    <Button @click="handleClick">切换</Button>
  </div>
</template>

<script lang="ts" setup>
import { defineModel, watch } from 'vue';

const model = defineModel();

const emit = defineEmits(['input']);

// 模拟用户“输入”行为:比如点击改变值
function handleClick() {
  emit('input', { target: { value: '1111111' } });
}
</script>

还有v-bind绑定$field.props

其他组件看源码:stackblitz.com/~/github.co…