Ejemplos
This content is not available in your language yet.
Cuatro ejemplos end-to-end con el form real renderizado. Cada demo es un <co-form> funcional — escribe, mira cómo cambian los valores y errores en el panel de la derecha, y dale submit para ver el payload final.
1. Signup (registro de usuario)
Sección titulada «1. Signup (registro de usuario)»Form típico con validación, errores traducidos, password con patrón, y submit.
Demo en vivo — interactúa con el form
Valores —
{} Errores
{} <script setup>import { ref } from 'vue';import { useForm, CoFormRenderer } from '@prolibu-suite/cobalt-form-vue';import { useRouter } from 'vue-router';import { useToast } from '@/composables/useToast';
const router = useRouter();const toast = useToast();const submitting = ref(false);
const schema = { firstName: { type: 'String', required: true, minLength: 2, maxLength: 50, label: 'Nombre' }, lastName: { type: 'String', required: true, minLength: 2, maxLength: 50, label: 'Apellido' }, email: { type: 'String', required: true, format: 'email', label: 'Email' }, password: { type: 'String', required: true, minLength: 8, label: 'Contraseña' }, newsletter:{ type: 'Boolean', default: true, label: 'Newsletter' },};
const form = useForm(() => ({ schema: { modelSchema: schema, locale: 'es' }, onSubmit: async (values) => { submitting.value = true; try { await api.signup(values); toast.success('Cuenta creada. Revisa tu email.'); router.push('/login'); } finally { submitting.value = false; } },}));</script>
<template> <CoFormRenderer :form="form" layout="grid"> <template #header> <h1>Crear cuenta</h1> </template> <template #footer> <co-button label="Crear cuenta" variant="primary" :disabled="!form.isValid.value || submitting" :loading="submitting" @click="form.submit" /> </template> </CoFormRenderer></template>2. Edición con datos prefetched
Sección titulada «2. Edición con datos prefetched»El form abre con datos existentes (simulando un edit). email es read-only, role viene de un enum, bio ocupa todo el ancho.
Demo — perfil prellenado
Valores —
{} Errores
{} <script setup>import { useForm, CoFormRenderer } from '@prolibu-suite/cobalt-form-vue';import { useUser } from '@/composables/useUser';
const props = defineProps({ userId: String });const { user, loading } = useUser(props.userId);
const form = useForm(() => ({ schema: { modelSchema: userSchema, locale: 'es' }, initialValues: user.value || {}, onSubmit: async (values) => { await api.updateUser(props.userId, values); },}));</script>
<template> <div v-if="loading">Cargando…</div> <CoFormRenderer v-else :form="form" layout="grid"> <template #footer> <co-button label="Cancelar" variant="ghost" :disabled="!form.isDirty.value" @click="form.reset" /> <co-button label="Guardar cambios" variant="primary" :disabled="!form.isValid.value || !form.isDirty.value" @click="form.submit" /> </template> </CoFormRenderer></template>Lo interesante:
form.isDirtysolo estruecuando el usuario cambia algo respecto al estado prefetched.- “Cancelar” llama
reset()para volver al estado original. - “Guardar” se deshabilita si no hay cambios.
3. Form de settings (tipos variados)
Sección titulada «3. Form de settings (tipos variados)»Mezcla de todos los tipos: string con patrón, number con rango, boolean, enum, date.
Demo — todos los tipos de campo
Valores —
{} Errores
{} Probá:
- Dejar el slug con mayúsculas → ves el error del pattern
- Bajar los asientos a
0→ error demin - Cambiar el plan → se actualiza al instante en el panel de valores
4. Multi-step (wizard)
Sección titulada «4. Multi-step (wizard)»Wizard de 3 pasos con validación por paso. Usa useForm directamente para tener control total del renderizado entre pasos.
Demo — paso 1 del wizard (datos personales)
Valores —
{} Errores
{} Demo — paso 2 (datos de la empresa)
Valores —
{} Errores
{} <script setup>import { ref, computed } from 'vue';import { useForm } from '@prolibu-suite/cobalt-form-vue';
const step = ref(1);
const schema = { firstName: { type: 'String', required: true, label: 'Nombre' }, lastName: { type: 'String', required: true, label: 'Apellido' }, email: { type: 'String', required: true, format: 'email', label: 'Email' }, companyName: { type: 'String', required: true, label: 'Empresa' }, companySize: { type: 'String', enum: ['1-10', '11-50', '51-200', '200+'], required: true, label: 'Tamaño', }, industry: { type: 'String', required: true, label: 'Industria' },};
const fieldsByStep = { 1: ['firstName', 'lastName', 'email'], 2: ['companyName', 'companySize', 'industry'],};
const form = useForm(() => ({ schema: { modelSchema: schema, locale: 'es' }, onSubmit: async (values) => api.completeOnboarding(values),}));
const currentStepValid = computed(() => fieldsByStep[step.value].every((name) => !form.errors.value[name]?.length));
const next = () => { fieldsByStep[step.value].forEach((name) => form.touch(name)); if (currentStepValid.value) step.value++;};</script>Patterns clave:
- Un solo
useFormpara todo el wizard. No hagas un form por paso. - Validación por paso vía
currentStepValidque solo mira los campos del paso actual. - Touched solo on-demand — solo marcamos touched al intentar avanzar.
Tips de producción
Sección titulada «Tips de producción»- Loading durante submit: usa
form.isSubmitting.valuepara mostrar spinner en el botón. El controller la setea automáticamente duranteonSubmit. - Toasts post-submit: emitir desde el componente o desde
onSubmit. No tiresawaitsin try/catch o perderás errores silenciosamente. - Reset entre instancias: si tu drawer se reutiliza, observa el
openy llamaform.reset(newInitialValues)al abrir. - Dirty check al cerrar: si
form.isDirty.valueestruecuando el usuario cierra el drawer, pregunta antes de descartar cambios.